蓦然回首,有好久不能够在休息日里去学习新知识、新技能,也好久没有把遇到的问题记录到博客中。往往只能够在工作日时,做好业务上的实现。今年求职过程中,竟然被问到了Java9,我甚至连Java8的函数式编程都没掌握明白。入职某药企,发现在其项目代码中大篇幅的使用函数式编程,左思右想,决定写记录一下Java8中stream的特性,增强自己的记忆力。
首先,Stream作为Java8的一大亮点,它与java.io包里的InputStream和OutputStream是完全的两个概念。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作(bulk data operation)。
Stream API 借助于同样新出现的 Lambda 表达式,而且使用并发模式,极大的提高编程效率和程序可读性。
另外,Stream有几个特性:
1.Stream不改变数据源,会产生一个新的集合
2.Stream不存储数据,只是按照特定规则进行计算
3.Stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行
从源码中不难看出,Stream提供的方法有很多,缩短时间,提取其中常用的几种方法进行说明。源码在java.util.stream.Stream 目录下,有时间的同学可以去研究研究。
代码如下(示例):
@Test
public void test1(){
Integer[] numArr = {1, 2, 3, 4, 5};
List<Integer> list = Stream.of(numArr).collect(Collectors.toList());
log.info("list:{}",JSONObject.toJSONString(list));
}
将流转换为其他形式,接收一个Collect接口实现。
Collectors.toList()是Java 8 流的新类 java.util.stream.Collectors 实现了 java.util.stream.Collector 接口,同时又提供了大量的方法对流 ( stream ) 的元素执行 map and reduce 操作,或者统计操作。
Collectors.toList() 是将流中的所有元素导出到一个列表( List )中。
代码如下(示例):
List<User> userList = new ArrayList<>();
userList.add(new User(3, "张一鸣"));
userList.add(new User(1, "zym"));
userList.add(new User(2, "zhangyiming"));
// 提取User的Name转成List集合
List<String> nameList = userList.stream()
.map(User::getName).collect(Collectors.toList());
System.out.println(nameList);
该方法将list泛型对象中某一个属性提取,重新汇入一个list对象接收。输出为所有name。
代码如下(示例):
List<Integer> numList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6});
// 取出集合中的所有偶数
numList = numList.stream()
.filter(num -> num % 2 == 0).collect(Collectors.toList());
System.out.println(numList );
在项目代码中也经常会使用到过滤属性,其目的是将当前list中,筛选出符合条件的参数,生成一个新Stream。
// 字符串拼接
String[] arr = {"a", "b", "c", "d"};
String content = Stream.of(arr).reduce("", String::concat);
System.out.println(content); // 输出 abcd
// 求和, 需要一个起始参数值
int sum = Stream.of(1, 2, 3, 4, 5, -2).reduce(0, Integer::sum);
System.out.println(sum); // 输出 13
// 找最大值
int maxNum = Stream.of(1, 3, 5, -2, 0).reduce(Integer::max).get();
System.out.println(maxNum); // 输出 5
BinaryOperator类表示对两个相同类型的操作数的运算,并产生与该操作数相同类型的结果,进入BinaryOperator源码查看,发现@FunctionalInterface,定义函数式接口,所以reduce的参数就一目了然了。
在药企项目中发现一个比较奇怪的写法,查询库表把所有信息查询出来,通过Stream进行相关的条件过滤,利用sorted进行排序 返回至前台,我不太确定这样做是否能够提高性能,日后有时间出一篇性能比较。
基本DB层的数据拿过来后,利用Stream相关方法进行了过滤、分组、去重、排序。
代码如下(示例):
Integer[] numArr = {2, 3, 1, 5, 0 ,8};
List<Integer> numList = Stream.of(numArr)
.sorted().collect(Collectors.toList());
System.out.println(numList); // 输出[0, 1, 2, 3, 5, 8]
// 反向排序
numList = Stream.of(numArr)
.sorted(Comparator.reverseOrder()).collect(Collectors.toList());
System.out.println(numList);
以上就是关于Stream相关用法,时间关系,很多源码解读及运行过程未做详细说明,只提取了几种常用的方法给大家参考。同时,在使用性能上似乎存在了问题,关于Stream的性能问题我也阅读了很多文章,等日后有时间做一次性能比较后再进行补充。
不足之处,请批评指正