Java 流有序/无序问题
我有以下代码:Java 流有序/无序问题,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下代码: Set<Integer> l = new TreeSet<>(); l.add(1); l.add(10); l.add(3); l.add(-3); l.add(-4); 但是forEach总是返回已排序的集合 然后,我对以下句子还有另一个疑问: 对于连续流,存在或不存在遭遇顺序 不影响性能,只影响决定论。如果流是有序的, 在相同的服务器上重复执行相同的流管道 来源将产生相同的结果;如果没有订购, 重复执行可能会产生不同的结果 事实上,如果我在无序流上
Set<Integer> l = new TreeSet<>();
l.add(1);
l.add(10);
l.add(3);
l.add(-3);
l.add(-4);
但是forEach
总是返回已排序的集合
然后,我对以下句子还有另一个疑问:
对于连续流,存在或不存在遭遇顺序
不影响性能,只影响决定论。如果流是有序的,
在相同的服务器上重复执行相同的流管道
来源将产生相同的结果;如果没有订购,
重复执行可能会产生不同的结果
事实上,如果我在无序流上尝试此代码,结果总是相同的,并且不会产生不同的结果:
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
Arrays.stream( new int[]{8, -1, 3}).forEach(System.out::println);
我真的不理解这个API部分…操作没有执行任何显式对流进行无序排序的操作。它所做的是删除流上必须保持有序的约束,从而允许后续操作使用不必考虑有序的优化
您可以在以下网站上阅读:
对于连续流,相遇顺序的存在或不存在并不影响性能,只影响确定性。如果对流进行排序,则在相同的源上重复执行相同的流管道将产生相同的结果;如果不按顺序执行,重复执行可能会产生不同的结果。对于并行流,放松排序约束有时可以实现更高效的执行。
在流具有遭遇顺序但用户并不特别关心该遭遇顺序的情况下,使用unordered()显式地对流进行反排序可能会提高某些有状态或终端操作的并行性能
您使用的是树集,它对元素进行排序。因此,这些要素将是: -4,-3,1,3,10 使用串行流不会改变顺序,因此结果不依赖于有序/无序流的属性,正如您在第一个示例“串行流”中看到的(以及您自己注意到的) 结果:-4-3110
l.stream().unordered().map(s->s+" ").forEach(System.out::print);
结果:-4-3110
l.stream().unordered().map(s->s+" ").forEach(System.out::print);
如果使流并行,则可以创建多个线程,并且不再保证结果,因为这取决于特定的执行。还要注意的是,forEach()不是一个有序的操作,这意味着只要它的管道中有东西要处理,它就会执行。
请参见“并行流上的无序操作”示例:
结果:310-31-4
l.stream().unordered().map(s->s+" ").parallel().forEach(System.out::print);
结果:3-4-3110
在并行流中使用有序操作(如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。每次执行代码时,此结果可能会(也可能不会)改变,因为我们指定顺序并不重要。
l.stream().unordered().parallel().skip(2).limit(2).findFirst().ifPresent(System.out::print);
以下是完整的代码:
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");
}
publicstaticvoidmain(字符串[]args){
设置l=新树集();
l、 增加(1);
l、 增加(10);
l、 增加(3);
l、 增加(-3);
l、 增加(-4);
System.out.println(“串行流”);
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(“并行流上的无序操作”);
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(“并行流上的有序操作”);
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
并行流上的有序操作
一,
-3是的,但文档中写着:“一些中间操作,如sorted(),可能会对一个无序的流施加遭遇顺序,而另一些可能会使一个有序的流无序,如BaseStream.unordered()”,事实上,如果我对一个未排序的集合调用sorted,它会排序……当然,但是排序后的流仍然可以作为无序流传递,它只是没有留下任何关于它的保证。因此,为了消除排序约束,我们使用
unorder()
和foreach()
方法?如果是这样的话,为什么我们有两种方法来做同样的事情呢?当你在处理串行流时,它甚至没有任何意义,所以当你在处理串行流时,每次运行代码时都看不到不同的结果?
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");
}