Stream

4 阅读3分钟

什么是 Stream

Stream 是 Java 8 引入的一个新特性,位于 java.util.stream 包中。它提供了一种函数式编程风格的操作方式,用于处理集合数据。Stream 允许你以声明性方式(类似于 SQL 语句)处理数据,而不是通过命令式编程。

Stream 的特点

  • 声明性:使用 Stream 可以以声明性方式处理数据,代码更简洁、可读性更高。
  • 链式操作Stream 支持链式操作,可以将多个操作组合在一起。
  • 惰性求值Stream 的中间操作是惰性求值的,只有在终端操作执行时才会实际处理数据。
  • 并行处理Stream 支持并行处理,可以利用多核处理器的优势,提高性能。

创建 Stream

从集合创建

import java.util.Arrays;  
import java.util.List;  
import java.util.stream.Stream;

public class StreamExample {  
    public static void main(String[] args) {  
        List<String> list = Arrays.asList("a""b""c");  
        Stream<String> stream = list.stream();  
    }  
}

从数组创建

import java.util.stream.Stream;

public class StreamExample {  
    public static void main(String[] args) {  
        String[] array = {"a""b""c"};  
        Stream<String> stream = Arrays.stream(array);  
    }  
}

使用静态方法创建

import java.util.stream.Stream;

public class StreamExample {  
    public static void main(String[] args) {  
        Stream<String> stream = Stream.of("a""b""c");  
    }  
}

Stream 的常用操作

中间操作

  • filter:过滤元素。
  • map:将元素转换为另一种形式。
  • flatMap:将每个元素转换为一个流,然后将这些流合并为一个流。
  • distinct:去重。
  • sorted:排序。
  • limit:截取前 N 个元素。
  • skip:跳过前 N 个元素。

终端操作

  • forEach:对每个元素执行操作。
  • collect:将流转换为其他形式(如集合)。
  • reduce:将流中的元素组合成一个值。
  • count:计算元素数量。
  • anyMatchallMatchnoneMatch:匹配操作。
  • findFirstfindAny:查找元素。

示例代码

使用 Stream 进行过滤和映射

import java.util.Arrays;  
import java.util.List;  
import java.util.stream.Collectors;

public class StreamExample {  
    public static void main(String[] args) {  
        List<String> list = Arrays.asList("apple""banana""cherry""date");

        // 使用 Stream 进行过滤和映射  
        List<String> result = list.stream()  
                                  .filter(s -> s.startsWith("a"))  
                                  .map(String::toUpperCase)  
                                  .collect(Collectors.toList());

        System.out.println(result); // 输出: [APPLE]  
    }  
}

使用 Stream 进行聚合操作

import java.util.Arrays;  
import java.util.List;

public class StreamExample {  
    public static void main(String[] args) {  
        List<Integer> list = Arrays.asList(12345);

        // 使用 Stream 计算总和  
        int sum = list.stream()  
                      .reduce(0, Integer::sum);

        System.out.println("Sum: " + sum); // 输出: Sum: 15  
    }  
}

Stream 与传统编程方式的区别

  • 声明性Stream 提供了一种声明性编程方式,代码更简洁、可读性更高。例如,使用 Stream 可以直接描述要做什么,而不是如何做。
List<String> result = list.stream()
    .filter(s -> s.startsWith("a"))  
    .map(String::toUpperCase)  
    .collect(Collectors.toList());
  • 命令式:传统编程方式是命令式的,需要明确地描述每一步操作。例如,使用循环和条件语句来实现相同的功能。
List<String> result = new ArrayList<>();  
for (String s : list) {  
    if (s.startsWith("a")) {  
        result.add(s.toUpperCase());  
    }  
}

链式操作 vs 分步操作

  • 链式操作Stream 支持链式操作,可以将多个操作组合在一起,代码更简洁。
    list.stream()  
        .filter(s -> s.startsWith("a"))  
        .map(String::toUpperCase)  
        .forEach(System.out::println);
  • 分步操作:传统编程方式通常需要分步操作,每一步都需要单独处理。
    for (String s : list) {  
        if (s.startsWith("a")) {  
            System.out.println(s.toUpperCase());  
        }  
    }

并行处理

  • 并行处理Stream 支持并行处理,可以利用多核处理器的优势,提高性能。
    list.parallelStream()  
        .filter(s -> s.startsWith("a"))  
        .map(String::toUpperCase)  
        .forEach(System.out::println);
  • 传统处理:传统编程方式需要手动管理线程和同步,代码复杂度较高。
    // 需要手动管理线程和同步

总结

  • Stream:提供了一种函数式编程风格的操作方式,用于处理集合数据,支持声明性编程、链式操作、惰性求值和并行处理。
  • 传统编程方式:命令式编程,需要明确地描述每一步操作,代码可读性较低,难以并行处理。