在Java8中运行以下流示例:

System.out.println(Stream

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

.reduce("", (s1, s2) -> s1 +"/" + s2)

);

收益率:

/a/b/c/d/e/f

当然-这并不奇怪。

由于http://docs.oracle.com/javase/8/docs/api/index.html?overview-summary.html,流是顺序执行还是并行执行并不重要:

Except for operations identified as explicitly nondeterministic, such as findAny(), whether a stream executes sequentially or in parallel should not change the result of the computation.

AFAIK reduce()是确定性的,而(s1, s2) -> s1 +"/" + s2是关联的,因此添加parallel()应该会产生相同的结果:

System.out.println(Stream

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

.parallel()

.reduce("", (s1, s2) -> s1 +"/" + s2)

);

但是我的机器上的结果是:

/a//b//c//d//e//f

怎么了

顺便说一句:使用(首选).collect(Collectors.joining("/"))而不是reduce(...)对于顺序执行和并行执行会产生相同的结果a/b/c/d/e/f。

JVM详细信息:

java.specification.version: 1.8

java.version: 1.8.0_31

java.vm.version: 25.31-b07

java.runtime.version: 1.8.0_31-b13

实际上,似乎特别声明了,如果您的BinaryOperator是关联的,那么它应该适用于并行流。

正如其他答复者所指出的那样,除了不遵循减少的规则外,还有一种更简单的方法可以完成您的工作:stream.collect(joining(""))

从reduce的文档中:

The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t.

在您的情况下,这是不正确的-"和" a"创建为" / a"。

我已经提取了累加器功能并添加了打印输出以显示发生了什么:

BinaryOperator accumulator = (s1, s2) -> {

System.out.println("joining "" + s1 +"" and "" + s2 +""");

return s1 +"/" + s2;

};

System.out.println(Stream

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

.parallel()

.reduce("", accumulator)

);

这是示例输出(运行之间有所不同):

joining"" and"d"

joining"" and"f"

joining"" and"b"

joining"" and"a"

joining"" and"c"

joining"" and"e"

joining"/b" and"/c"

joining"/e" and"/f"

joining"/a" and"/b//c"

joining"/d" and"/e//f"

joining"/a//b//c" and"/d//e//f"

/a//b//c//d//e//f

您可以在函数中添加if语句以分别处理空字符串:

System.out.println(Stream

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

.parallel()

.reduce((s1, s2) -> s1.isEmpty()? s2 : s1 +"/" + s2)

);

正如Marko Topolnik所注意到的,由于累加器不一定是可交换函数,因此不需要检查s2。

太好了!因此,使用不使用身份的reduce也可以解决问题.reduce((s1, s2) -> s1 +"" + s2)。

最好使用条件表达式,恕我直言:(s1, s2) -> s1.isEmpty()? s2 : s2.isEmpty()? s1 : s1 +"" + s2

另外,由于累加器功能不需要交换,因此您实际上不需要检查s2是否为空。因此,(s1, s2) -> s1.isEmpty()? s2 : s1+""+s2就足够了。

或者他可以使用stream.collect(Collectors.joining("","",""))

@mk。这不是真的。第一步可以在3个线程中并行完成,分别创建a / b,c / d和e / f。然后,我们可以将前两个加入创建a / b / c / d,然后将其与e / f加入创建a / b / c / d / e / f。我在考虑身份是否会给我们带来任何好处,但是我找不到任何很好的解释-将功能与身份元素一起使用是多余的操作,它只会产生第二个元素。

因此,最大的问题是,为什么实现不能仅在内部将reduce(identity, accumulator)委托给reduce(accumulator).orElse(identity),因为" accumulator.apply(identity, t)等于t"的要求意味着在每个评估线程中执行whatever=accumulator.apply(identity, whatever)是胡说八道。

@Holger也许仅仅是因为它与FP纯粹主义者不合时宜:)

正是这一点:a + 0 != a。我没有阅读reduce文档中的注释。 +1

要添加其他答案,

您可能要使用Mutable减少,文档指定执行类似

String concatenated = strings.reduce("", String::concat)

会给出不良的性能结果。

We would get the desired result, and it would even work in parallel.

However, we might not be happy about the performance! Such an

implementation would do a great deal of string copying, and the run

time would be O(n^2) in the number of characters. A more performant

approach would be to accumulate the results into a StringBuilder,

which is a mutable container for accumulating strings. We can use the

same technique to parallelize mutable reduction as we do with ordinary

reduction.

因此,您应该改用StringBuilder。

对于刚开始使用lambda和流的人来说,花了很长时间才到达" AHA"时刻,直到我真正了解这里发生了什么。我会对此重新措辞,以使像我这样的新手流变得更轻松(至少我希望它真的得到了答复)。

所有这些都在reduce文档中指出:

标识值必须是累加器功能的标识。这意味着对于所有t,accumulator.apply(identity,t)等于t。

我们可以轻松证明代码的方式,关联性被破坏:

static private void isAssociative() {

BinaryOperator operator = (s1, s2) -> s1 +"/" + s2;

String result = operator.apply("","a");

System.out.println(result);

System.out.println(result.equals("a"));

}

一个空字符串与另一个字符串串联,应该真正产生第二个字符串。这不会发生,因此累加器(BinaryOperator)不具有关联性,因此在并行调用的情况下,reduce方法不能保证相同的结果。

操作员的关联性没有被破坏,唯一的问题是身份值。参见docs.oracle.com/javase/8/docs/api/java/util/stream/

java 并行 执行进度_关于java:Java8流的顺序执行和并行执行产生不同的结果?相关推荐

  1. java命令行参数_一个 java 命令行参数顺序的坑

    tream Stream是在Java SE 8 API添加的用于增强集合的操作接口,可以让你以一种声明的方式处理集合数据.将要处理的集合看作一种流的创建者,将集合内部的元素转换为流并且在管道中传输, ...

  2. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  3. java中变量 关键字_基于java的voliate关键字详解

    voliate关键字的作用: 一.内存可见性 基于缓存一致性协议,当用voliate关键字修饰的变量改动时,cpu会通知其他线程,缓存已被修改,需要更新缓存.这样每个线程都能获取到最新的变量值. 二. ...

  4. java代码的执行机制_关于java代码的执行机制

    转载于:https://blog.csdn.net/houfeng777123/article/details/74316748 1.Java代码执行流程 ·第一步:*.java-->*.cla ...

  5. java 如何循环执行一个对象_一个Java对象到底有多大?

    编写Java代码的时候,大多数情况下,我们很少关注一个Java对象究竟有多大(占据多少内存),更多的是关注业务与逻辑.但是殊不知,在我们不经意间,大量的内存被无形地浪费了. 一个Java对象到底有多大 ...

  6. 用标号跳出当前多重嵌套循环是否继续执行循环_在Java中如何跳出当前的多重嵌套循环?...

    在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,更多Java专业知识,广州疯狂java培训为你讲解; 1.在java中如何跳出当前的 ...

  7. java是什么格式_是java格式

    错误:编码GBK的不可映射字符的解决办法 最近在重新补javaSE的基础,编辑器编写完代码以后,在控制台运行代码段的时候,出现了以下的错误提示:错误:编码GBK的不可映射字符 在通过查询谷哥和度娘以后 ...

  8. java account函数的_用Java进行同时函数调用 - java

    在我的应用程序中,我以以下方式加载缓存. 加载用户缓存loadUserCache(); 加载帐户缓存loadAccountCache(); 加载客户缓存loadCustomerCache(); 上述每 ...

  9. java内存模型浅析_浅析java内存模型

    原标题:浅析java内存模型 Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型--又称为Java内存模型 ...

最新文章

  1. 《大数据导论》一第1章 理解大数据
  2. 无人值守网络安装Linux系统
  3. BZOJ 1562 变换序列
  4. yarn下载依赖慢的解决方法
  5. python函数的作用域_python学习第五篇 函数 变量作用域
  6. Latex中文期刊论文模板
  7. 怎么发现愿景和目标 | 进击
  8. 思科计算机考试期末,Cisco期末考试选择题题库.doc
  9. Linux系统load average异常值处理的trick
  10. 自然语言处理之维特比(Viterbi)算法
  11. Codeforces Round #570 (Div. 3)B. Equalize Prices
  12. 钢琴 |《小汤普森简易钢琴教程》第一册
  13. c语言输出所有汉字代码例题
  14. RTSP 和 RTMP原理 通过ffmpeg实现将本地摄像头推流到RTSP服务器
  15. iOS Mac小白必备的基本操作
  16. 3032. 是坚挺数吗?
  17. 如何减少页面的重绘和回流(14)
  18. IO流如何选择字节流和字符流??
  19. Open_CV形态学运算专题 (腐蚀膨胀、开闭运算、梯度运算、顶帽运算黑帽运算 )【Python-Open_CV系列(十)】
  20. 阿里云视频点播获取视频播放信息nodejs版

热门文章

  1. 传递命令行参数示例代码 (C 和 Python)
  2. 值得收藏的45个Python优质资源
  3. C语言如何获取结构体中指定元素的大小?sizeof ( (X*)0 ) -> Y)(空指针操作)
  4. 黑马程序员C语言基础(第三天)
  5. html <link>标签
  6. Python中的正则表达式(分组)
  7. Java进阶:ReentrantLock和Condition基本使用
  8. windows10下同时安装两个mysql服务的解决办法
  9. 你对Java网络编程了解的如何?Java NIO 网络编程 | Netty前期知识(二)
  10. JavaWeb 入门篇(1)Maven创建Web项目 Idea配置tomcat