java8函数式编程 视频_java8函数式编程调试<四>

继续看《java 8 函数式编程》,思考一些传达的设计思路吧。我们在调试时通常会设置断点,单步跟踪程序的每一步。使用流时,调试可能会变得更加复杂,因为迭代已交由类库控制,而且很多流操作是惰性求值的。

然后先说一下java8由外部迭代到内部迭代,java程序员在使用集合类时,我们长做的事情就是在集合上进行迭代,然后处理返回的每一个元素。然后作者可能觉得每次迭代,需要写不少样本代码,并且将for循环改造成并行方式也很麻烦。for循环其实算是一个封装了迭代的语法糖,一般首先调用 iterator 方法,产生一个新的 Iterator 对象,进而控制整 个迭代过程,这就是外部迭代,书中给的图也不错。

6bb884bc9ba6b9e45de60e4f303bd639.png

这从本质上来讲是一种串行化操作,总体来看,使用 for 循环会将行为和方法混为一谈。另一种方法就是内部迭代,首先要注意 stream() 方法的调用,该方法不是返回一个控制迭代的 Iterator 对象,而是返 回内部迭代中的相应接口:Stream。

e2f15b9eec0de5f7b8e90efdbc95f522.png

由于Stream API的函数式编程风格,我们并没有改变集合的内容,而是描述出Stream里的内容。判断一个操作是惰性求值还是及早求值很简单:只需看它的返回值。如果返回值是 Stream, 那么是惰性求值;如果返回值是另一个值或为空,那么就是及早求值。使用这些操作的理想方式就是形成一个惰性求值的链,最后用一个及早求值的操作返回想要的结果,这正是它的合理之处。整个过程和建造者模式有共通之处。建造者模式使用一系列操作设置属性和配置,最后调用一个 build 方法,这时,对象才被真正创建。

调试时通常会设置断点,单步跟踪程序的每一步,但是我们经常在集合上遍历,然后操作数据,你是要测试代码,希望看到每一步的操作结果是什么,在每一步中打印出集合的值,这个在for循环中是很容易做到的,但是现在事惰性求值的流中,这就比较复杂了。

当然在流中 有forEach操作,但是这样我们就无法操作流了,可以看到forEach返回的结果是void,如果我们还要使用流,那必须要重新创建一遍,好尴尬的代码呀。

f6b2e0e0c2f601bce51ab45618eb4c5a.png

但是java的设计者都是大神呀,给我们提供了解决方案,那就是使用peak,可以让我们查看每一个值,同时能继续操作流,这就是我们的peak方法了。

bf728de6cb3c407c5e27de89c4c2d064.png

当然,我们都在应用中使用日志系统(eg..log4j,slf4j),据说peek也可以用同样的方式,将输出定向到日志系统中,下次试试看。毕竟查bug看栈信息 ,更直接的是看日志。peek是个中间操作,它提供了一种对流中所有元素操作的方法,而不会把这个流消费掉。

但是如果不写后面的collect求值操作,发现peek什么都不输出,流遇到及早求值的时候,才会真正去遍历和执行,还要写在求值操作前,有点奇葩,因为peek操作返回的还是一个流,当然peek可以写在filter后 map后多次写是没问题的。

1cbe0fab24ff602885c571c0aa801bbf.png

121da5daf6e0c0e55fc9c0d7706db10f.png

这么说peek到底怎么运作的

c522a8b6f4d5d36aa5a371e69e61b565.png

你觉得输出的日志会是什么?

e475fb2c43cc955d3615fdbfc8a308ba.png

微信公众号:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值