简体   繁体   English

流有序/无序问题

[英]Stream ordered/unordered problems

I have the following code:我有以下代码:

Set<Integer> l = new TreeSet<>();
l.add(1);
l.add(10);
l.add(3);
l.add(-3);
l.add(-4);

and I want to unorder the collection with:我想用以下命令对集合进行排序:

l.stream().unordered().forEach(System.out::println);

but the forEach returns always the collection ordered!但是forEach总是返回有序的集合!

Then I have also another doubt about the below sentence from here :然后我对这里的以下句子还有另一个疑问:

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism.对于顺序流,遇到顺序的存在与否不会影响性能,只会影响确定性。 If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result;如果流是有序的,在相同的源上重复执行相同的流管道将产生相同的结果; if it is not ordered, repeated execution might produce different results.如果没有排序,重复执行可能会产生不同的结果。

In fact if I try this code on an unordered stream the results is always the same and never produce different results:事实上,如果我在无序流上尝试这段代码,结果总是相同的,永远不会产生不同的结果:

Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);

I really don't understand this API part...我真的不明白这个API部分......

The unordered() operation doesn't do any actions to explicitly unorder the stream. unordered()操作不会执行任何操作来显式取消流的排序。 What it does is that it removes the constraint on the stream that it must remain ordered, thereby allowing subsequent operations to use optimizations that don't have to take ordering into consideration.它的作用是消除流上必须保持有序的约束,从而允许后续操作使用不必考虑排序的优化。

You can read about this in the Java 8 docs :您可以在Java 8 文档中阅读有关此内容的信息:

For sequential streams, the presence or absence of an encounter order does not affect performance, only determinism.对于顺序流,遇到顺序的存在与否不会影响性能,只会影响确定性。 If a stream is ordered, repeated execution of identical stream pipelines on an identical source will produce an identical result;如果流是有序的,在相同的源上重复执行相同的流管道将产生相同的结果; if it is not ordered, repeated execution might produce different results.如果没有排序,重复执行可能会产生不同的结果。
For parallel streams, relaxing the ordering constraint can sometimes enable more efficient execution.对于并行流,放宽排序约束有时可以实现更高效的执行。
... ...

In cases where the stream has an encounter order, but the user does not particularly care about that encounter order, explicitly de-ordering the stream with unordered() may improve parallel performance for some stateful or terminal operations.在流具有遇到顺序但用户并不特别关心该遇到顺序的情况下,使用 unordered() 显式对流进行排序可能会提高某些有状态或终端操作的并行性能。

You are using a TreeSet, which orders the elements.您正在使用 TreeSet,它对元素进行排序。 So, the elements will be:因此,元素将是:

-4, -3, 1, 3, 10 -4, -3, 1, 3, 10

Using a serial stream does not change the order, so the result is not dependent on the property of the stream of being ordered/unordered, as you can see in the first example "Serial Stream" (and as you noticed yourself).使用串行流不会改变顺序,因此结果不依赖于有序/无序流的属性,如您在第一个示例“串行流”中所见(以及您自己注意到的)。

l.stream().map(s->s+" ").forEach(System.out::print);

Result: -4 -3 1 3 10结果:-4 -3 1 3 10

l.stream().unordered().map(s->s+" ").forEach(System.out::print);

Result: -4 -3 1 3 10结果:-4 -3 1 3 10

If you make the stream parallel , then more than one thread can be created and the result is no longer guaranteed, because it depends on the specific execution.如果将流设置为 parallel ,则可以创建多个线程并且不再保证结果,因为这取决于具体的执行。 Note also that forEach() is not an ordered operation , meaning that it executes whenever it has something to process in its pipeline.还要注意forEach() 不是有序操作,这意味着只要它的管道中有东西要处理,它就会执行。 See the example "Unordered Operations on a Parallel Stream":请参阅示例“并行流上的无序操作”:

l.stream().parallel().map(s->s+" ").forEach(System.out::print);

Result: 3 10 -3 1 -4结果:3 10 -3 1 -4

l.stream().unordered().map(s->s+" ").parallel().forEach(System.out::print);

Result: 3 -4 -3 1 10结果:3 -4 -3 1 10

Things change when you use Ordered Operations (like findFirst(), limit() and skip()) in a parallel stream.当您在并行流中使用有序操作(如 findFirst()、limit() 和 skip())时,情况会发生变化。 When you use findFirst() in a pipeline, what you really want is having the first element, according to the order of the elements in the stream, you just don't want any element, in which case you would be using findAny().当您在管道中使用 findFirst() 时,您真正想要的是拥有第一个元素,根据流中元素的顺序,您只是不想要任何元素,在这种情况下,您将使用 findAny() . To have deterministic results by these operations, you lose the benefits of using a parallel stream, because the execution has to be serialized to process the elements in a specific order.要通过这些操作获得确定性结果,您将失去使用并行流的好处,因为必须将执行序列化以按特定顺序处理元素。

   l.stream().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);

Result: 1 .结果:1。 This result will always be the same, no matter how many times you execute the code.无论您执行代码多少次,此结果将始终相同。

l.stream().unordered().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);

Result: -3 .结果:-3。 This result may (or may not) change every time you execute the code, because we specified that the order is not important.每次执行代码时,此结果可能(也可能不会)改变,因为我们指定了顺序并不重要。

Here is the complete code:这是完整的代码:

public static void main(String[] args) {
    Set<Integer> l = new TreeSet<>();
    l.add(1);
    l.add(10);
    l.add(3);
    l.add(-3);
    l.add(-4);

    System.out.println("Serial Stream");
    l.stream().map(s->s+" ").forEach(System.out::print);
    System.out.println();
    l.stream().unordered().map(s->s+" ").forEach(System.out::print);
    System.out.println("\n");

    System.out.println("Unordered Operations on a Parallel Stream");
    l.stream().parallel().map(s->s+" ").forEach(System.out::print);
    System.out.println();
    l.stream().unordered().map(s->s+" ").parallel().forEach(System.out::print);
    System.out.println("\n");

    System.out.println("Ordered Operations on a Parallel Stream");
    l.stream().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);
    System.out.println();
    l.stream().unordered().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);
    System.out.println("\n");

}

Serial Stream串行流

-4 -3 1 3 10 -4 -3 1 3 10

-4 -3 1 3 10 -4 -3 1 3 10

Unordered Operations on a Parallel Stream并行流上的无序操作

3 10 -3 -4 1 3 10 -3 -4 1

-3 1 3 10 -4 -3 1 3 10 -4

Ordered Operations on a Parallel Stream并行流上的有序操作

1 1

-3 -3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM