在Java 8流中没有索引的原因是什么?
我想知道Java 8流( Stream
),他们有以下方法:
-
forEach(Consumer action)
-
forEachOrdered(Consumer action)
反对不提供以下签名的论点是什么?
-
forEachOrdered(BiConsumer action)
- 然后,它将返回流中项目的索引和项目本身。
使用此重载,可以在订购流时实际使用索引。
我真的很好奇,看看它的论点是什么。
编辑 ,对于具有forEachRemaining
Iterator
实际上也适用,并且可能包含更多类。
如果没有类提供这样的选项,那么我怀疑它已被考虑用于Java 8并被拒绝。
索引每个元素需要按顺序分配索引。 这将破坏并行操作的要点,因为每个操作都必须同步才能获得其索引。
Stream
s和Iterator
不必是有限的。 Stream::generate
和Stream::iterate
返回无限的Stream
。 您将如何使用无限流处理索引? 让指数溢出到负数? 使用BigInteger
(可能会耗尽内存)?
处理无限流的索引没有很好的解决方案,因此设计人员(正确地说,在我看来)将其排除在API之外。
添加提供索引的单个方法将需要将所有实现方法加倍,以使一个维护索引而一个不加索引。 除了在API中可见之外,它还有更多内容。 如果您很好奇,可以查看内部接口java.util.stream.Sink
的类型树以获得一个想法。 所有这些都会受到影响。 另一种方法是即使不需要也始终保持索引。
它增加了一种模糊性。 索引是否反映了源索引,即在过滤时没有改变,或者它是最终流中的位置 ? 另一方面,您始终可以插入从项类型到保存项的类型的映射以及链中任何位置的索引。 这将清除模糊性。 该解决方案的局限性与JRE提供的解决方案相同。
在Iterator
的情况下,答案更简单。 由于forEachRemaining
必须作为default
接口方法提供,因此无法添加索引的维护。 因此,在调用它时,它不知道到目前为止已消耗了多少项。 当时以零开始计数,忽略所有先前的项目将成为很多开发人员会提出更多疑问的function。
我已经阅读了上述所有答案,但是,我个人不同意这些答案。 我认为应该添加一些方法(例如indexed())并且它可以顺序执行,即使在并行流中也是如此,因为这种方法将快速validation,不需要并行执行。 您可以按地图添加’index’。 例如:
List list = N.asList("a", "b", "c"); final AtomicLong idx = new AtomicLong(0); list.stream().map(e -> Indexed.of(idx.getAndIncrement(), e)).forEach(N::println);
或者你可以使用第三个库: AbacusUtil ,代码将是:
List list = N.asList("a", "b", "c"); Stream.of(list).indexed().forEach(N::println); // output: // [0]=a // [1]=b // [2]=c
披露:我是AbacusUtil的开发人员。