《Java8 Stream介绍》
1、为什么需要 Stream
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 是一个函数式语言+多核时代综合影响的产物。
2、小例子
在详细介绍之前,看一个例子(例子来源于:http://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/)
假设有这样一个需求:如果要发现 type 为 grocery 的所有交易,然后返回以交易值降序排序好的交易 ID 集合
我们一般的写法如下:
List<Transaction> groceryTransactions = new Arraylist<>();
//第一步:在所有的交易集合中,得到所有type为grocery的所有交易
for(Transaction t: transactions){
if(t.getType() == Transaction.GROCERY){
groceryTransactions.add(t);
}
}
//第二步:按照交易值降序排序
Collections.sort(groceryTransactions, new Comparator(){
public int compare(Transaction t1, Transaction t2){
return t2.getValue().compareTo(t1.getValue());
}
});
//第三步:得到最后的结果:ID集合
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
transactionsIds.add(t.getId());
}
如果对命令式编程和声明式编程者两个概念比较熟悉的朋友,可以很明显的看出,以上代码就是明显的“命令式编程”。
这里说下命令式编程和声明式编程的概念。
命令式编程:简单来说就是手把手的告诉机器怎么来做这个事情。即命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。
声明式编程:简单来说就是告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。
拉回到我们上面的应用场景,如果我们使用Stream来完成,写法如下:
List<Integer> transactionsIds = transactions.parallelStream().
filter(t -> t.getType() == Transaction.GROCERY).
sorted(comparing(Transaction::getValue).reversed()).
map(Transaction::getId).
collect(toList());
这是一段声明式编程的代码段,相比命令式,要简洁和清晰的多哈。在详细讲解Stream知识之前,稍微讲解一下上面代码的意思,不明白也没有关系,等把后面看完Stream知识之后再回头看这段代码也就相当容易了:
1、transactions.parallelStream():转化为并行Stream
2、filter(t -> t.getType() == Transaction.GROCERY):过滤只包含所有type为GROCERY的transaction。
3、sorted(comparing(Transaction::getValue).reversed()):根据指定的条件排序
4、map(Transaction::getId):得到每个transaction的ID
5、collect(toList()) 转化为List。
3、Stream
3.1、什么是Stream
Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等