Stream流式编程

如何创建 Stream 对象

从集合创建:我们可以通过调用集合的 stream() 方法来创建一个 Stream 对象。例如:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream();

从数组创建:Java 8 引入了 Arrays 类的 stream() 方法,我们可以使用它来创建一个 Stream 对象。例如:

String[] names = {"Alice", "Bob", "Carol"};
Stream<String> stream = Arrays.stream(names);

通过 Stream.of() 创建:我们可以使用 Stream.of() 方法直接将一组元素转换为 Stream 对象。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);

通过 Stream.builder() 创建:如果我们不确定要添加多少个元素到 Stream 中,可以使用 Stream.builder() 创建一个 Stream.Builder 对象,并使用其 add() 方法来逐个添加元素,最后调用 build() 方法生成 Stream 对象。例如:

Stream.Builder<String> builder = Stream.builder();
builder.add("Apple");
builder.add("Banana");
builder.add("Cherry");
Stream<String> stream = builder.build();

从 I/O 资源创建:Java 8 引入了一些新的 I/O 类(如 BufferedReaderFiles 等),它们提供了很多方法来读取文件、网络流等数据。这些方法通常返回一个 Stream 对象,可以直接使用。例如:

Path path = Paths.get("data.txt");
try (Stream<String> stream = Files.lines(path)) {
    // 使用 stream 处理数据
} catch (IOException e) {
    e.printStackTrace();
}

通过生成器创建:除了从现有的数据源创建 Stream,我们还可以使用生成器来生成元素。Java 8 中提供了 Stream.generate() 方法和 Stream.iterate() 方法来创建无限 Stream。例如:

Stream<Integer> stream = Stream.generate(() -> 0); // 创建一个无限流,每个元素都是 0
Stream<Integer> stream = Stream.iterate(0, n -> n + 1); // 创建一个无限流,从 0 开始递增

需要注意的是,Stream 对象是一种一次性使用的对象,它只能被消费一次。一旦对 Stream 执行了终止操作(如收集结果、遍历元素),Stream 就会被关闭,后续无法再使用。因此,在使用 Stream 时,需要根据需要重新创建新的 Stream 对象。

常用的 Stream 操作方法

过滤(Filter):filter() 方法接受一个 Predicate 函数作为参数,用于过滤 Stream 中的元素。只有满足 Predicate 条件的元素会被保留下来。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> filteredStream = stream.filter(n -> n % 2 == 0); // 过滤出偶数

映射(Map):map() 方法接受一个 Function 函数作为参数,用于对 Stream 中的元素进行映射转换。对每个元素应用函数后的结果会构成一个新的 Stream。例如:

Stream<String> stream = Stream.of("apple", "banana", "cherry");
Stream<Integer> mappedStream = stream.map(s -> s.length()); // 映射为单词长度

扁平映射(FlatMap):flatMap() 方法类似于 map() 方法,不同之处在于它可以将每个元素映射为一个流,并将所有流连接成一个流。这主要用于解决嵌套集合的情况。例如:

List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
Stream<Integer> flattenedStream = nestedList.stream().flatMap(List::stream); // 扁平化为一个流

截断(Limit):limit() 方法可以限制 Stream 的大小,只保留前 n 个元素。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> limitedStream = stream.limit(3); // 只保留前 3 个元素

跳过(Skip):skip() 方法可以跳过 Stream 中的前 n 个元素,返回剩下的元素组成的新 Stream。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> skippedStream = stream.skip(2); // 跳过前 2 个元素

排序(Sorted):sorted() 方法用于对 Stream 中的元素进行排序,默认是自然顺序排序。还可以提供自定义的 Comparator 参数来指定排序规则。例如:

Stream<Integer> stream = Stream.of(5, 2, 4, 1, 3);
Stream<Integer> sortedStream = stream.sorted(); // 自然顺序排序

去重(Distinct):distinct() 方法用于去除 Stream 中的重复元素,根据元素的 equals() 和 hashCode() 方法来判断是否重复。例如:

Stream<Integer> stream = Stream.of(1, 2, 2, 3, 3, 3);
Stream<Integer> distinctStream = stream.distinct(); // 去重

汇总(Collect):collect() 方法用于将 Stream 中的元素收集到结果容器中,如 List、Set、Map 等。可以使用预定义的 Collectors 类提供的工厂方法来创建收集器,也可以自定义收集器。例如:

Stream<String> stream = Stream.of("apple", "banana", "cherry");
List<String> collectedList = stream.collect(Collectors.toList()); // 收集为 List

归约(Reduce):reduce() 方法用于将 Stream 中的元素依次进行二元操作,得到一个最终的结果。它接受一个初始值和一个 BinaryOperator 函数作为参数。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Optional<Integer> sum = stream.reduce((a, b) -> a + b); // 对所有元素求和

统计(Summary Statistics):summaryStatistics() 方法可以从 Stream 中获取一些常用的统计信息,如元素个数、最小值、最大值、总和和平均值。例如:

IntStream stream = IntStream.of(1, 2, 3, 4, 5);
IntSummaryStatistics stats = stream.summaryStatistics();
System.out.println("Count: " + stats.getCount());
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());

以上只是 Stream API 提供的一部分常用操作方法,还有许多其他操作方法,如匹配(Match)、查找(Find)、遍历(ForEach)等

版权声明:
作者:郭靖
链接:https://www.sxszhian.com/archives/9621
来源:上海永驰网络科技有限公司
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>