Java 8 Stream

什么是 Stream

Stream(流)是一个来自数据源的元素队列并支持聚合操作。
在 Java 中,集合和数组是我们经常会用到的数据结构,但是在 Java 8 之前,集合和数组的处理并不是很便捷,
这一问题在 Java 8 中得到了改善,Java 8 API 添加了一个新的抽象称为流 Stream。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API 可以极大提高 Java 程序员的生产力,让程序员写出高效率、干净、简洁的代码。
流的处理,主要有三种关键性操作:分别是流的创建、中间操作(intermediate operation)以及最终操作(terminal operation)

Stream 的创建

通过已有的数组来创建流

1
2
String[] arr = new String[] {"ab", "cd", "ef"};
Stream<String> arrStream = Arrays.stream(arr);

通过已有的集合来创建流

1
2
List<String> strings = Arrays.asList("Hello", "World", "Hello World", "Hello Stream");
Stream<String> stream = strings.stream();

通过 Stream 创建流

1
Stream<String> stream = Stream.of("Hello", "World", "Hello World", "Hello Stream");

Stream 中间操作

中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新 stream。

filter

filter 用于通过设置的条件过滤出元素,以下代码使用 filter 方法过滤掉空字符串:

1
2
List<String> strings = Arrays.asList("Hello", "", "World", "Hello World", "Hello Stream");
strings.stream().filter(s -> !s.isEmpty()).forEach(System.out::println);

map

map 用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:

1
2
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().map(i -> i * i).forEach(System.out::println);

limit/skip

limit/skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素。以下代码片段使用 limit 方法保留4个元素:

1
2
3
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().limit(4).forEach(System.out::println);
numbers.stream().skip(4).forEach(System.out::println);

sorted

sorted 用于对流进行排序

1
2
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);

distinct

distinct 主要用来去重

1
2
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().distinct().forEach(System.out::println);

Stream 最终操作

最终操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以 pipeline 的方式执行,这样可以减少迭代次数。计算完成之后 stream 就会失效。

最终操作会消耗流,产生一个最终结果。也就是说,在最终操作之后,不能再次使用流,也不能在使用任何中间操作,否则将抛出异常。

常用的最终操作如下:

forEach

forEach 迭代流中的每个数据

1
2
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

count

count 用来统计流中的元素个数

1
2
List<String> strings = Arrays.asList("Hello", "Stream");
System.out.println(strings.stream().count());

collect

collect 一个归约操作,可以接受各种做法作为参数,将流中的元素累积成一个汇总结果

1
2
3
List<String> strings = Arrays.asList("Hello", "World", "Hello Stream");
strings = strings.stream().filter(s -> s.startsWith("Hello")).collect(Collectors.toList());
System.out.println(strings);

并行(parallel)程序

parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:

1
2
3
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();

Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

1
2
3
4
5
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

统计

一些产生统计结果的收集器也非常有用。它们主要用于 int、double、long 等基本类型上,它们可以用来产生类似如下的统计结果。

1
2
3
4
5
6
7
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

参考网址

本文结束啦 感谢您阅读
如果你觉得这篇文章对你有用,欢迎赞赏哦~
0%