我有以下代码:
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
总是返回订购的集合!
然后我对此sentence还有另一个疑问:
对于顺序流,是否存在遭遇订单 不影响表现,只影响决定论。如果订购了流, 在相同的流程上重复执行相同的流管道 源将产生相同的结果;如果没有订购, 重复执行可能会产生不同的结果。
事实上,如果在无序流上尝试此代码,结果总是相同的 并且永远不会产生不同的结果:
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
我真的不明白这个API部分...
答案 0 :(得分:13)
unordered()
操作不会执行任何操作来显式地对流进行排序。它的作用是消除了流必须保持有序的约束,从而允许后续操作使用不必考虑排序的优化。
您可以在Java 8 docs:
中了解相关信息对于顺序流,遇到顺序的存在与否不会影响性能,只影响确定性。如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果;如果没有订购,重复执行可能会产生不同的结果 对于并行流,放宽排序约束有时可以实现更高效的执行。
...如果流具有遭遇顺序,但用户并不特别关心该遭遇顺序,则使用unordered()显式地对流进行排序可以提高某些有状态或终端操作的并行性能。 / em>的
答案 1 :(得分:6)
您正在使用TreeSet,它对元素进行排序。因此,元素将是:
-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