java流有序/无序问题

eiee3dmh  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(363)

我有以下代码:

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

我想用以下方法对收藏进行无序排序:

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

但是 forEach 始终返回所订购的集合!
接下来我对下面这句话还有另一个疑问:
对于连续流,相遇顺序的存在与否不影响性能,只影响确定性。如果一个流被排序,在同一个源上重复执行相同的流管道将产生相同的结果;如果不排序,重复执行可能会产生不同的结果。
事实上,如果我在无序流上尝试此代码,结果总是相同的,并且不会产生不同的结果:

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

我真的不明白这个api部分。。。

lpwwtiir

lpwwtiir1#

这个 unordered() 操作不会执行任何操作来显式地对流进行无序排序。它所做的是移除流上必须保持有序的约束,从而允许后续操作使用不必考虑有序的优化。
您可以在java 8文档中了解这一点:
对于连续流,相遇顺序的存在与否不影响性能,只影响确定性。如果一个流被排序,在同一个源上重复执行相同的流管道将产生相同的结果;如果不排序,重复执行可能会产生不同的结果。
对于并行流,放松排序约束有时可以实现更高效的执行。
...
在流具有相遇顺序但用户并不特别关心该相遇顺序的情况下,使用unordered()显式地对流进行反排序可以提高某些有状态或终端操作的并行性能。

dnph8jn4

dnph8jn42#

您使用的是树集,它对元素进行排序。因此,要素将是:
-4, -3, 1, 3, 10
使用串行流不会改变顺序,因此结果不依赖于有序/无序流的属性,正如您在第一个示例“串行流”中看到的(以及您自己注意到的)。

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

结果:-4-3 1 3 10

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

结果:-4-3 1 3 10
如果使流并行,则可以创建多个线程,并且不再保证结果,因为这取决于特定的执行。还要注意foreach()不是一个有序操作,这意味着它在其管道中有东西要处理时就执行。参见示例“并行流上的无序操作”:

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

结果:3 10-3 1-4

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

结果:3-4-3 1 10
在并行流中使用有序操作(如findfirst()、limit()和skip())时,情况会发生变化。当您在管道中使用findfirst()时,您真正想要的是拥有第一个元素,根据流中元素的顺序,您只是不想要任何元素,在这种情况下,您将使用findany()。要通过这些操作获得确定的结果,就失去了使用并行流的好处,因为必须序列化执行以按特定顺序处理元素。

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

结果:1。无论执行代码多少次,结果都是一样的。

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

结果:-3。每次执行代码时,这个结果可能会(也可能不会)改变,因为我们指定顺序并不重要。
完整代码如下:

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");

}

串行流
-4 -3 1 3 10
-4 -3 1 3 10
并行流上的无序操作
3 10 -3 -4 1
-3 1 3 10 -4
并行流上的有序操作
1
-3

相关问题