java8stream中间操作_了解一下,Java8 Stream的中间操作顺序

介绍了Stream的中间操作顺序,对性能的影响,以及如何调优。

上篇文章讲了Stream的常用方法,可以先回顾一下:图解Java8 Stream,真香

垂直执行:map和filter

先看下面一个例子,找出流中"b"的字符串,并将其转化为大写,包含两个中间操作 map 和 filter 以及结束操作forEach。

Stream.of("a", "b", "c", "d", "e")

.map(str -> {

System.out.println("map: \t" + str);

return str.toUpperCase();

})

.filter(str -> {

System.out.println("filter: " + str);

return str.equals("B");

})

.forEach(str -> {

System.out.println("forEach: " + str);

});

// 控制台输出

map: a

filter: A

map: b

filter: B

forEach: B

map: c

filter: C

map: d

filter: D

map: e

filter: E

复制代码

由输出结果可以看出,map/filter/forEach 是垂直执行,map和filter执行了5次,forEach执行了1次。

如果我们改变操作顺序,filter方法最先执行,将大大减少执行的次数。

Stream.of("a", "b", "c", "d", "e")

.filter(str -> {

System.out.println("filter: " + str);

return str.equals("b");

})

.map(str -> {

System.out.println("map: \t" + str);

return str.toUpperCase();

})

.forEach(str -> {

System.out.println("forEach: " + str);

});

// 控制台输出

filter: a

filter: b

map: b

forEach: B

filter: c

filter: d

filter: e

复制代码

filter还是执行了5次,forEach执行了1次,但map降为了1次,也就是说符合filter的才会执行map操作,这种技巧在Stream流中有大量元素时,执行的更快。

水平执行:sorted

接下来,我们看下sorted排序操作,现学现卖,咱们把filter放在了map操作之前:

Stream.of("d", "b", "c", "a", "e")

.sorted((str1, str2) -> {

System.out.println("sorted: " + str1 + ", " + str2);

return str1.compareTo(str2);

})

.filter(str -> {

System.out.println("filter: " + str);

return str.equals("b");

})

.map(str -> {

System.out.println("map: \t" + str);

return str.toUpperCase();

})

.forEach(str -> {

System.out.println("forEach: " + str);

});

// 控制台输出

sorted: b, d

sorted: c, b

sorted: c, d

sorted: c, b

sorted: a, c

sorted: a, b

sorted: e, c

sorted: e, d

filter: a

filter: b

map: b

forEach: B

filter: c

filter: d

filter: e

复制代码

这时候发现,sorted操作是水平执行的,会对流中所有的元素进行排序,总共执行了8次。

我们再一次更改操作顺序,来尝试优化性能:

Stream.of("d", "b", "c", "a", "e")

.filter(str -> {

System.out.println("filter: " + str);

return str.equals("b");

})

.sorted((str1, str2) -> {

System.out.println("sorted: " + str1 + ", " + str2);

return str1.compareTo(str2);

})

.map(str -> {

System.out.println("map: \t" + str);

return str.toUpperCase();

})

.forEach(str -> {

System.out.println("forEach: " + str);

});

// 控制台输出

filter: d

filter: b

filter: c

filter: a

filter: e

map: b

forEach: B

复制代码

这次发现,sorted方法并没有被调用,因为被filter过滤之后,流中只剩下一个元素,也就不需要执行排序操作了。

而且,sorted对filter和map这种垂直执行的方法,具有截断作用,也就是说sorted前的中间操作,需要完全执行,形成一个完整的Stream流,交给sorted排序。

混合使用

举个例子,比如把"b"和"d"过滤出来,转为大写,并排序:

Stream.of("d", "b", "c", "a", "e")

.filter(str -> {

System.out.println("filter: " + str);

return str.equals("b") || str.equals("d");

})

.map(str -> {

System.out.println("map: \t" + str);

return str.toUpperCase();

})

.sorted((str1, str2) -> {

System.out.println("sorted: " + str1 + ", " + str2);

return str1.compareTo(str2);

})

.forEach(str -> {

System.out.println("forEach: " + str);

});

// 控制台输出

filter: d

map: d

filter: b

map: b

filter: c

filter: a

filter: e

sorted: B, D

forEach: B

forEach: D

复制代码

因为sorted的截断作用,先垂直执行filter和map,然后水平执行sorted,最后垂直执行forEach。

小结

在编写复杂的Stream方法链时,一般应该把filter操作放到最前边,以减少后续操作的压力,这一点在Stream流中有大量元素时更为明显。

而且,你最好把上边的代码自己运行下,看看输出结果,你会理解的更深刻,下一节,咱们聊聊Stream的高级操作。

留个思考题:Stream.sorted方法,底层的排序算法是什么?欢迎留言区讨论。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值