持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
流的概念
流是Java API的新成员,允许以声明的方式去处理数据集合,通过查询表达式的语句来实现,流还还可以透明的并行的处理数据,无须编写任何多线程的代码。
流的对比
以下是展示使用Java7 和 Java8分别去统计喜欢m豆的投票数量20以下的都有哪些,并且中间需要进行排序,查看最少的州是多少。
public void useJava7() {
List<MnmInfo> list = new ArrayList<>();
List<MnmInfo> lowerCountList = new ArrayList<>();
for (MnmInfo mnmInfo : list) {
if (mnmInfo.getCount() < 20) {
lowerCountList.add(mnmInfo);
}
}
Collections.sort(lowerCountList, new Comparator<MnmInfo>() {
@Override
public int compare(MnmInfo o1, MnmInfo o2) {
return Integer.compare(o1.getCount(), o2.getCount());
}
});
// 排序完成之后,获取每种颜色的出现的次数
Map<String, List<MnmInfo>> map = new HashMap<String, List<MnmInfo>>();
for (MnmInfo mnmInfo : lowerCountList) {
List<MnmInfo> mnmInfos = map.get(mnmInfo.getColor());
if (mnmInfos == null) {
mnmInfos = new ArrayList<MnmInfo>();
}
mnmInfos.add(mnmInfo);
}
}
可以看出代码非常的多,并且不加以注释说明的话,需要仔细阅读代码才知道这段代码想要做的事情。并且中间还多保存了中间结果,这会导致内存的消耗,并且在数据量大的情况下,将成为一个性能瓶颈。
以下是使用Java8流式代码
public void useJava8() {
List<MnmInfo> list = new ArrayList<>();
Map<String, List<MnmInfo>> aggList = list.stream()
.filter(m -> m.getCount() < 20)
.sorted(comparing(MnmInfo::getCount))
.collect(groupingBy(MnmInfo::getColor));
}
从视觉上就非常明显的看出来了两者的差异性了,首先在代码数量上,使用Java8的流式代码非常的简洁,并且可以叠加多种复合操作,比如进一步的filter,或者是map都是可以的。整段代码下来都是以声明式的方式进行编写的,即使没有注释,也可以让阅读的人一目了然代码要做的事情。
众多周知,Java的并发编程是非常的难的,要写出没有问题,并且性能优异的代码对于编写者的要求非常的高,但是引入了Java8的流模式以后,这段代码可以随时的扩展成多线程的并发代码。只需要将stream切换成parallelStream即可,是不是显得非常的不可思议。
流操作
流的操作会分为两大类:可以把流连接起来的操作称为中间操作,类似filter,可以把流进行关闭的操作成为终端操作。类似我们刚才看到的collect。
中间操作
中间操作会返回另一个流,这可以让多个操作连接起来成为一个查询。中间操作不会真正执行任何的处理,因为它们都是惰性求值的,直到触发一个终端操作。因为有很多的中间操作可以进行合并的执行的。 中间操作有以下几种,如图表所示。
终端操作
终端操作会从流的流水线生成结果,其结果是任何不适流的值,比如List,Integer,甚至Void。
流的组成
流的组成包含三个部分,整个使用方式也类似于构建者模式
- 一个数据源(如集合)来执行一个查询,从数据库或者外部数据源获取的数据集合
- 一个中间操作链,形成一条流的流水线,用来进行各种数据过滤以及数据转换
- 一个终端操作,统计生成一个最终结果
实战
筛选数据
可以利用Lambda表达式的谓词过滤,筛选你需要的数据集部分。
dataList.stream().filter(d -> d.getCount() > 20);
选择前n个
对于排序等操作,可能需要前10名。
dataList.stream().sorted(comparing(MnmInfo::getCount)).limit(10);
除去前n个
对于排序完的数据,我们肯能想知道除了第10-第20位的数据
dataList.stream().sorted(comparing(MnmInfo::getCount)).skip(10).limit(10);
数据转换
对于筛选好的数据,我们不需要那么多,只需要提前对应的名称即可。
List<String> collect = dataList.stream().limit(10).map(MnmInfo::getCa).collect(toList());
相同的数据集扁平化压缩
以下代码可以找出单词列表中各不相同的数组。
List<String> distinctLetters = Arrays.asList("Hello", "World").stream().map(word -> word.split("")).flatMap(Arrays::stream).distinct().collect(toList());
总结
Java Stream流的作用不止于此,还有一些统计方式的计算的。将数据进行分组聚合的。