什么是Stream API
关于stream,IBM对其有一个概括。链接
Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。
怎么使用stream API
获得一个stream对象
对于实现了List
接口的对象,获取stream非常简单。
List<Integer> nums = new ArrayList<>();
Stream<Integer> stream = nums.stream();
调用List
的stream()
方法,即可得到一个Stream
对象。
而对于int[]
一类的数组,获取stream也不是很困难。
int[] nums = {1, 2, 3, 4, 5, 6, 7};
IntStream stream = Arrays.stream(nums);
由于Java的基本数据类型导致的问题,此处的stream不再为Stream<T>
类型(毕竟int并不是对象),而是一个所谓的IntStream
,不过这并不影响其的使用。要获得Stream<Integer>
类型的stream,我们只需要将数组更换为Integer[]
类型。
Integer[] nums = {1, 2, 3, 4, 5, 6, 7};
Stream<Integer> stream = Arrays.stream(nums);
stream有什么用?
获得了一个stream对象之后,我们就可以开始利用它。
求数组长度
最简单的,调用stream.count()
方法,即可获得数组的长度。
Integer[] nums = {1, 2, 3, 4, 5, 6, 7};
Stream<Integer> stream = Arrays.stream(nums);
long size = Arrays.stream(nums).count();
//上下两行代码等价
size = nums.length;
有人可能会说,就这?这只是stream最简单的使用,接着来些好玩的例子。
统计不及格学生的学号
Map<String, Integer> score = new HashMap<>();
score.put("201806061100", 95);
score.put("201806061101", 75);
score.put("201806061102", 53);
score.put("201806061103", 54);
score.put("201806061104", 77);
score.keySet().stream()
.filter(key -> score.get(key) < 60)
.forEach(key -> System.out.println(key));
该例子使用了stream的filter方法,其中使用了一个lambda表达式,传入一个key,返回key所对应的value是否小于60。这个filter会返回所有成绩低于60分的学生的学号。
接下来,使用了forEach方法,继续利用lambda表达式,将这些学号依次输出。
将stream转回List
List<String> blame = score.keySet().stream()
.filter(key -> score.get(key) < 60)
.collect(Collectors.toList());
使用collect方法,指定转换方式为toList
,即可将其转回List<String>
对值进行额外的处理
score.keySet().stream()
.filter(key -> score.get(key) < 60)
.map(key -> key.substring(8))
.forEach(key->System.out.println(key));
在这里,我们使用了一个新方法 map
,可以将其解释为映射
。.map(key -> key.substring(8))
,会返回一个新的stream对象,其中的每一项都执行了 .substring(8)
的操作。
排序
Map<String, Integer> score = new HashMap<>();
score.put("201806061100", 95);
score.put("201806061101", 75);
score.put("201806061102", 53);
score.put("201806061103", 54);
score.put("201806061104", 77);
score.keySet().stream()
.sorted((k1, k2) -> score.get(k2) - score.get(k1))
.forEach(key -> System.out.println(key));
使用 sorted
方法,并在其中实现一个比较器,即可完成按照成绩从高到低的顺序进行排序。
更多有趣的方法
有关stream的方法还有很多,读者可自行进入Java的文档进行了解,本文不再进行介绍。