31 | 加餐1:带你吃透课程中Java 8的那些重要知识点(一)
该思维导图由 AI 生成,仅供参考
如何在项目中用上 Lambda 表达式和 Stream 操作?
- 深入了解
- 翻译
- 解释
- 总结
Java 8的新特性包括Lambda表达式和Stream操作的使用。文章通过具体例子展示了如何在项目中应用这些特性,以及如何使用Java 8简化代码。除了介绍Lambda表达式的初衷和类型系统匹配,还演示了使用Stream简化集合操作、Optional简化判空逻辑以及JDK8结合Lambda和Stream对各种类的增强。此外,还介绍了Java 8中其他类的函数式API的增强,如HashMap的缓存操作和Files.walk返回Path流的应用。文章通过丰富的案例和技术细节,为读者展示了Java 8的强大功能和简化代码的能力。另外,文章还介绍了并行流的功能,以及五种不同方式实现并行操作的比较。总的来说,本文适合Java开发人员学习和参考,尤其对于想要深入了解Java 8新特性的开发人员来说,是一篇非常有价值的文章。
《Java 业务开发常见错误 100 例》,新⼈⾸单¥59
全部留言(33)
- 最新
- 精选
- 小阳置顶疑问: 代码3 的执行代码 ,forkJoinPool.execute(() -> IntStream.rangeClosed(1, taskCount).parallel().forEach(i -> increment(atomicInteger))); 我的理解是 通过自定义的forkJoinPool来将并行任务提交到公共的forkJoinPool去执行,因为 paraller().forEach()执行过程中并没提供像代码5那样设置用户的forkJoinPool,您说是在自定义的forkJoinPool执行increment(atomicInteger)的,这是为什么呢?
作者回复: 看一下ForkJoinTask.fork()方法你就明白为什么能使用到自定义的ForkJoinPool了: public final ForkJoinTask<V> fork() { Thread t; if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ((ForkJoinWorkerThread)t).workQueue.push(this); else ForkJoinPool.common.externalPush(this); return this; }
2020-03-1810 - Darren置顶疑问:匿名内部类和Lambda到底有什么区别?为什么匿名内部类会生成$1这样的class文件而Lambda并没有??? 回答下问题: 1.项目中现在基本都是在使用Lambda表达式,主要是因为使用的vert.x和RxJava2,响应式变成基本都是Lambda; 2.并行效果消失,和去掉parallel()的效果是一样的,因为forEachOrdered将按照其源指定的顺序处理流的元素,而不管流是连续的还是并行的。 JavaDoc: forEach:The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism. -------谷歌翻译------ 此操作的行为明确地是不确定的。 对于并行流管道,此操作不能保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。 对于任何给定的元素,可以在库选择的任何时间和线程中执行操作。 如果操作访问共享状态,则它负责提供所需的同步。 forEachOrdered :Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. -------谷歌翻译----- 如果流具有定义的遇到顺序,则按流的遇到顺序对此流的每个元素执行操作。
作者回复: lambda与普通的匿名内部类的实现方式不一样,可以参考一些资料,比如https://colobu.com/2014/11/06/secrets-of-java-8-lambda/ 这篇总结的很好: 编译时: - Lambda 表达式会生成一个方法, 方法实现了表达式的代码逻辑 - 生成invokedynamic指令, 调用bootstrap方法, 由java.lang.invoke.LambdaMetafactory.metafactory方法实现 运行时: - invokedynamic指令调用metafactory方法。 它会返回一个CallSite, 此CallSite返回目标类型的一个匿名实现类, 此类关联编译时产生的方法 - lambda表达式调用时会调用匿名实现类关联的方法。 forEachOrdered会让整个遍历过程失去并行化的效能,可以参考代码中的ForEachOrderedTest
2020-03-17319 - 👽置顶检查下代码中是否有使用匿名类,以及通过遍历 List 进行数据过滤、转换和聚合的代码,看看能否使用 Lambda 表达式和 Stream 来重新实现呢? 已经使用lambda,stream快一年了,匿名类,基本就通过idea的自动处理,自己使用的基本上就:forEach,filter,map,这些。 对于并行流部分的并行消费处理 1 到 100 的例子,如果把 forEach 替换为 forEachOrdered,你觉得会发生什么呢? 个人猜测是会被有序化地多线程执行,四核CPU,1234 等一秒5678 这样。 但是,实际上,并发能力被直接移除。1等一秒,2等一秒,3......这样。不严谨的猜测,forEachOrdered 将本来的打印加上了类似于synchronized的效果。
作者回复: forEachOrdered 会让parallelStream丧失部分的并行能力,主要是forEach的逻辑无法并行起来,比较: private void stream() { IntStream.rangeClosed(1, 10).filter(ForEachOrderedTest::filter).forEach(ForEachOrderedTest::consume); } private void parallelStream() { IntStream.rangeClosed(1, 10).parallel() .filter(ForEachOrderedTest::filter) .forEach(ForEachOrderedTest::consume); } private void parallelStreamForEachOrdered() { IntStream.rangeClosed(1, 10).parallel() .filter(ForEachOrderedTest::filter) .forEachOrdered(ForEachOrderedTest::consume); }
2020-03-172 - 退而结网这个课程未免也太划算了,这个加餐囊括了好多其他的内容,物超所值,为老师点赞!打call
作者回复: 后续加餐干货同样很多
2020-03-1816 - 刘大明想问下老师,既然Lambda 表达式这么简洁,方便,但是我们项目经理要我们在项目中不要使用他,说是不好调试.......这个是理由吗?
作者回复: 其实IDEA已经增加了非常方便的Stream调试功能,可以参考https://www.jetbrains.com/help/idea/analyze-java-stream-operations.html
2020-03-17611 - 杰哥长得帅想问一下大佬,把受检异常转换为运行时异常,有什么作用呢
作者回复: 因为Function的签名不抛出受检异常IOException的,我们只能在flatMap中进行try...catch...了,这样就很不优雅臃肿,所以我们转换为运行时异常,这样就可以用一行代码来写完整个逻辑了
2020-03-283 - 大头从传递对象,到传递匿名内部类,再到lambda表达式的演化,去掉了重复的代码,仅保留有意义的代码,越来越简洁明了了
作者回复: 是,不仅仅是简化,函数式的概念其实从更本上可以改变设计的
2020-03-183 - mgs2002forEachOrdered 保证元素按顺序执行,我测试了代码的例子,发现去掉parallel后执行时间跟forEach差不多,加上后执行时间快了一倍多,结论是forEachOrdered并没有使parallel并行化效果完全消失,是这样的吗,也尝试看了一下源码,有点蒙。。 以下是我的测试结果 246810421086246810StopWatch '': running time = 23068739988 ns --------------------------------------------- ns % Task name --------------------------------------------- 15051360863 065% stream 2010090132 009% parallelStream 6007288993 026% parallelStreamForEachOrdered
作者回复: 因为filter还是并行的
2020-03-173 - 👽java8的Lambda,给程序员提供了极大的便利性,和大幅度简化代码的可能性。单纯使用的话,学习成本并不高。常用的主流的操作也就那么几个。 但是要自行定义,并灵活变通使用,还是需要花些功夫去学习练习的。
作者回复: 没错
2020-03-173 - 陈天柱我实际开发的时候,最喜欢用的lambda表达式就是将一个集合对象转换成由该对象的指定字段值组成的集合,以前只会用,看了老师的文章以后才意识到学东西还是需要系统! 关于第二个思考题,尝试去阅读了一下源码,发现完全懵逼了,所以直接用idea跑了一下代码发现并行流forEachOrderd的效果直接是串行化了,虽然使用了并行流,但需要让任务有序化,让我想起了RocketMq里的顺序消息。
作者回复: 可以比较一下源码中的ForEachOrderedTest
2020-03-172