请考虑以下代码:
System.out.println("#1");
Stream.of(0, 1, 2, 3)
.peek(e -> System.out.println(e))
.sorted()
.findFirst();
System.out.println("\n#2");
IntStream.range(0, 4)
.peek(e -> System.out.println(e))
.sorted()
.findFirst();
Run Code Online (Sandbox Code Playgroud)
输出将是:
#1
0
1
2
3
#2
0
Run Code Online (Sandbox Code Playgroud)
谁能解释一下,为什么两个流的输出不同?
Era*_*ran 51
嗯,IntStream.range()返回a sequential ordered IntStream from startInclusive(inclusive) to endExclusive (exclusive) by an incremental step of 1,这意味着它已经排序。既然已经排序了,那么下面的.sorted()中间操作什么都不做是有道理的。结果,peek()只在第一个元素上执行(因为终端操作只需要第一个元素)。
另一方面,传递给的元素Stream.of()不一定已排序(并且该of()方法不检查它们是否已排序)。因此,.sorted()必须遍历所有元素才能产生排序流,这允许findFirst()终端操作返回排序流的第一个元素。结果,peek对所有元素都执行,即使终端操作只需要第一个元素。
Eug*_*ene 33
IntStream.range在已经进行排序:
// reports true
System.out.println(
IntStream.range(0, 4)
.spliterator()
.hasCharacteristics(Spliterator.SORTED)
);
Run Code Online (Sandbox Code Playgroud)
所以当sorted()Stream 上的方法被命中时,在内部,它会变成一个 NO-OP。
否则,正如您在第一个示例中已经看到的那样,所有元素都必须排序,只有这样findFirst才能判断谁是“真正的第一个”。
请注意,此优化仅适用于自然排序的流。例如:
// prints too much you say?
Stream.of(new User(30), new User(25), new User(34))
.peek(x -> System.out.println("1 : before I call first sorted"))
.sorted(Comparator.comparing(User::age))
.peek(x -> System.out.println("2 : before I call second sorted"))
.sorted(Comparator.comparing(User::age))
.findFirst();
Run Code Online (Sandbox Code Playgroud)
其中(为简洁起见):
record User(int age) { }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2265 次 |
| 最近记录: |