每个有状态中间流 API 操作是否保证新的源集合?

2022-09-01 08:54:00

以下陈述是否属实?

该操作是“有状态中间操作”,这意味着后续操作不再对支持集合进行操作,而是对内部状态进行操作。sorted()

来源来源 - 它们似乎相互复制或来自同一来源。

免責聲明:我知道以下片段不是Java Stream API的合法用法。不要在生产代码中使用。

我已经测试了 Stream::排序为来自上述来源的片段:

final List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());
    
list.stream()
    .filter(i -> i > 5)
    .sorted()
    .forEach(list::remove);

System.out.println(list);            // Prints [0, 1, 2, 3, 4, 5]

它的工作原理。我将 Stream::sorted 替换为 Stream::d istinctStream::limitStream::skip

final List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());
    
list.stream()
    .filter(i -> i > 5)
    .distinct()
    .forEach(list::remove);          // Throws NullPointerException

令我惊讶的是,它被扔了。NullPointerException

所有测试方法都遵循有状态中间操作特性。然而,Stream::sorted 的这种独特行为没有记录,流操作和管道部分也没有解释有状态中间操作是否真的保证了新的源集合。

我的困惑从何而来,对上述行为的解释是什么?


答案 1

API 文档不保证“后续操作不再在支持集合上运行”,因此,您永远不应该依赖特定实现的此类行为。

你的例子碰巧偶然做了想要的事情;甚至不能保证 创建的 by 支持该操作。Listcollect(Collectors.toList())remove

显示反例

Set<Integer> set = IntStream.range(0, 10).boxed()
    .collect(Collectors.toCollection(TreeSet::new));
set.stream()
    .filter(i -> i > 5)
    .sorted()
    .forEach(set::remove);

抛出一个 .原因是实现优化了此方案,因为源已排序。原则上,它可以对原始示例执行相同的优化,就像以不指定的顺序显式执行操作一样,因此,排序是不必要的。ConcurrentModificationExceptionforEach

还有其他可以想象的优化,例如 可以转换为“查找最小值”操作,而无需将元素复制到新存储中进行排序。sorted().findFirst()

因此,底线是,当依赖于未指定的行为时,今天可能发生的事情,明天可能会中断,当添加新的优化时。


答案 2

好吧,必须是流管道的完整复制屏障,毕竟您的源可能无法排序;但这并没有被记录下来,因此不要依赖它。sorted

这不仅仅是关于本身,而是可以对流管道进行哪些其他优化,因此可以完全跳过。例如:sortedsorted

List<Integer> sortedList = IntStream.range(0, 10)
            .boxed()
            .collect(Collectors.toList());

    StreamSupport.stream(() -> sortedList.spliterator(), Spliterator.SORTED, false)
            .sorted()
            .forEach(sortedList::remove); // fails with CME, thus no copying occurred 

当然,需要成为一个完整的障碍,并停止做一个完整的排序,除非,当然,它可以跳过,因此文档没有做出这样的承诺,所以我们不会在奇怪的惊喜中运行。sorted

distinct另一方面,不必是完全的屏障,所有不同的做法是一次检查一个元素,如果它是唯一的;因此,在检查单个元素(并且它是唯一的)之后,它被传递到下一阶段,因此不会成为完整的屏障。无论哪种方式,这都没有记录...


推荐