相关疑难解决方法(0)

Java 8 Stream中的forEach vs forEachOrdered

我知道这些方法的执行顺序不同,但在我的所有测试中,我都无法实现不同的顺序执行.

例:

System.out.println("forEach Demo");
Stream.of("AAA","BBB","CCC").forEach(s->System.out.println("Output:"+s));
System.out.println("forEachOrdered Demo");
Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("Output:"+s));
Run Code Online (Sandbox Code Playgroud)

输出:

forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC
Run Code Online (Sandbox Code Playgroud)

请提供两种方法产生不同输出的示例.

java foreach java-8 java-stream

71
推荐指数
3
解决办法
4万
查看次数

规范是否保证顺序Java流上的操作必须保留在当前线程中?

规范是否保证顺序 Java Streams 上的所有操作都在当前线程中执行?("forEach"和"forEachOrdered"除外)

我明确要求规范,而不是当前的实现.我可以自己查看当前的实现,不需要打扰你.但实现可能会改变,还有其他实现.

我问因为ThreadLocals:我使用的是一个内部使用ThreadLocals的Framework.即使像company.getName()这样的简单调用最终也会使用ThreadLocal.我无法改变该框架的设计方式.至少不在理智的时间内.

这里的规范似乎令人困惑.包"java.util.stream"的文档说明:

如果行为参数确实有副作用,除非明确说明,否则不能保证这些副作用对其他线程的可见性,也不保证同一流管道中"相同"元素的不同操作在同一个线程中执行.

...

即使当管道被约束以产生结果,其与流源的遭遇顺序一致(例如,IntStream.range(0,5).parallel()地图(X - > X*2).toArray( )必须产生[0,2,4,6,8]),不能保证制成,以作为对于所述映射器函数被应用到各个元件,或为了在什么螺纹任何行为参数被执行对于给定的元件.

我将其解释为:流上的每个操作都可以在不同的线程中发生.但是"forEach"和"forEachOrdered"的文档明确指出:

对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.

如果每个流操作都可能发生在未指定的线程中,那么该语句将是多余的.因此恰恰相反:串行流上的所有操作都保证在当前线程中执行,除了"forEach"和"forEachOrdered"?

我搜索了关于"Java","Stream"和"ThreadLocal"组合的权威答案,但没有发现任何内容.该关闭的事情是由一个答案作者Brian Goetz在这里对堆栈溢出一个相关的问题,但它是有关订单,而不是线程,它只是对"的forEach",而不是其他流的方法:是否Stream.forEach尊重遇到顺序流的顺序?

java thread-local java-8 java-stream

15
推荐指数
1
解决办法
264
查看次数

在Java 8中,顺序和有序流保证按顺序执行操作吗?

是否有一个操作的任何保证连续有序流的处理,遭遇订单

我的意思是,如果我有这样的代码:

IntStream.range(0, 5)
        .map(i -> {
            myFunction(i);
            return i * 2;
         })
         .boxed()
         .collect(toList());
Run Code Online (Sandbox Code Playgroud)

是否有保证,它将以生成范围的遭遇顺序执行myFunction()调用?

我找到了Stream类的JavaDocs草案,明确说明了这一点:

对于顺序流管道,如果管道源具有已定义的遭遇顺序,则所有操作都以管道源的遭遇顺序执行.

但在官方JavaDocs中,这一行被删除了.它现在仅讨论所选方法的遭遇顺序.该包装java.util.stream文档副作用款规定:

即使管道被约束以产生与流源的遭遇顺序一致的结果(例如,IntStream.range(0,5).parallel().map(x -> x*2).toArray()必须产生[0, 2, 4, 6, 8]),也不保证将映射器函数应用于各个元素的顺序,或者什么线程为给定元素执行任何行为参数.

但它没有说明顺序流,而且这个例子是针对并行流的(我的理解是顺序流和并行流都是如此,但这是我不确定的部分).

另一方面,它也在订购部分说明:

如果订购了流,则大多数操作都被约束为对其遭遇顺序中的元素进行操作; 如果流的源是List包含的[1, 2, 3],那么执行的结果map(x -> x*2)必须是[2, 4, 6].但是,如果源没有定义的遭遇顺序,则值的任何排列[2, 4, 6]都将是有效结果.

但这一次它以"对元素进行操作"开始,但是示例是关于产生的流,所以我不确定它们是否会考虑副作用,副作用实际上就是这个问题.

java java-stream

11
推荐指数
1
解决办法
1088
查看次数

Java,哪个线程是顺序流执行的?

在阅读有关流的文档时,我遇到了以下句子:

  • ...试图从行为参数中访问可变状态会给你一个错误的选择...如果你没有同步访问那个状态,你就有数据竞争,因此你的代码被破坏...... [1]

  • 如果行为参数确实有副作用...... [没有]保证在同一个线程中执行同一流管道中"相同"元素的不同操作.[2]

  • 对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.[3]

这些句子不区分顺序流和并行流.所以我的问题是:

  1. 在哪个线程中执行顺序流的管道?它始终是调用线程还是可以自由选择任何线程的实现?
  2. 在流是顺序的情况下,哪个线程是forEach终端操作的action参数?
  3. 使用顺序流时是否必须使用任何同步?

java foreach java-8 java-stream

8
推荐指数
1
解决办法
632
查看次数

有序流上的减少是按顺序减少的吗?

我有一个ListA,B,C.

C reduce A reduce B != A reduce B reduce C (但是,减少(B减少C)是可以的).

换句话说,我的还原操作是关联的,但不是可交换的.

java是否对有序顺序流(例如列表中的默认流)执行减少将始终根据遭遇顺序进行减少?也就是说,java会重新排序减少(这样B减少A而不是A减少B)?

(希望这很清楚).

编辑添加一个小演示,也许有助于澄清

Stream.of(" cats ", " eat ", " bats ")
  .reduce("", (a, b) -> a + b); // cats eat bats
Run Code Online (Sandbox Code Playgroud)

有了上述,输出可能是"蝙蝠猫吃"​​或"吃蝙蝠猫"?是否在规范的某处保证了?

java java-8 java-stream

7
推荐指数
2
解决办法
1165
查看次数

如何对 Java 8 流进行单元测试?

list.stream().forEach(e -> { dbCall.delete(e.Id());});

列表中的每一项都会从数据库中删除。

假设列表中有3项,如何进行单元测试:

  1. 删除被调用了 3 次。
  2. 删除被称为“按顺序/顺序”,即列表中元素的顺序?

java testing unit-testing java-stream

5
推荐指数
1
解决办法
1万
查看次数

Java Stream:forEach 和 forEachOrdered 之间的区别

前提:我已经阅读了这个问题和其他问题,但我需要一些澄清。

我知道该Stream.forEach方法在处理并行流时(不仅)有所不同,这解释了为什么

//1
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.forEachOrdered(item -> System.out.print(item));
Run Code Online (Sandbox Code Playgroud)

印刷

one two three four five six
Run Code Online (Sandbox Code Playgroud)

但是当涉及到中间操作时,当流并行化时,顺序就不再保证了。所以这段代码

//2
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.peek(item -> System.out.print(item))
.forEachOrdered(item -> System.out.print(""));
Run Code Online (Sandbox Code Playgroud)

会打印类似的东西

four six five one three two 
Run Code Online (Sandbox Code Playgroud)

说该forEachOrdered方法仅影响其自身执行中的元素顺序是否正确?直觉上,我认为//1示例与

//3
Stream.of("one ","two ","three ","four ","five ","six ")
.parallel()
.peek(item -> System.out.print("")) //or any other intermediate operation
.sequential()
.forEach(item -> System.out.print(item));
Run Code Online (Sandbox Code Playgroud)

难道是我的直觉错了?我是否遗漏了整个机制的某些内容?

java foreach java-8 java-stream

3
推荐指数
1
解决办法
2794
查看次数

Stream.sorted().forEach()是否按预期工作?

在处理Java项目时,我遇到了如下所示的代码:

someMap.keySet().stream().sorted().forEach(/* ... */);
Run Code Online (Sandbox Code Playgroud)

根据键的自然顺序,这里的意图显然是为地图中的每个键做一些事情,这似乎是在实践中发生的事情.但是,我不确定这种行为是否得到保证.Javadoc for Stream#forEach说:

此操作的行为明确是不确定的.对于并行流管道,此操作不保证遵守流的遭遇顺序,因为这样做会牺牲并行性的好处.对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.

我知道如果代码使用.parallelStream().stream()不是保证它不能保证工作,但由于它使用的是顺序流(Javadoc没有说什么),我不确定.这是保证始终有效,还是代码需要使用.forEachOrdered()而不是.forEach()它?

编辑:我认为这个问题不是Java 8 StreamforEach vs forEachOrdered的重复,因为这个问题是"一般来说forEach和forEachOrdered之间有什么区别的例子",并且接受的答案基本上是"并行流" .这个问题具体是关于顺序流.

java language-lawyer java-stream

3
推荐指数
1
解决办法
1053
查看次数

每个和每个流的使用优点和缺点

从java 8开始迭代通过列表我可以使用两者:

List list = new ArrayList();
1. list.forEach(...)
2. list.stream().forEach(...)
Run Code Online (Sandbox Code Playgroud)

使用第二种情况有什么好处吗?要将列表转换为流?

java java-8 java-stream

2
推荐指数
1
解决办法
336
查看次数