Spliterator trySplit返回类型

And*_*rew 5 java lambda java-8 spliterator

我在java.util.Spliterator (Java 8)中偶然发现了一个有趣的细节.

方法trySplit()应该返回Spliterator的一个实例null,如果它不能被拆分.java doc说如下:

 * @return a {@code Spliterator} covering some portion of the
 * elements, or {@code null} if this spliterator cannot be split.
Run Code Online (Sandbox Code Playgroud)

在我看来,它是一个完美的使用场所java.util.Optional.根据javadoc:

 * A container object which may or may not contain a non-null value.
Run Code Online (Sandbox Code Playgroud)

有什么理由,为什么不使用Optional?

除了lambda-dev邮件列表中的这个问题外,谷歌搜索没有多大帮助,但没有回答.

Stu*_*rks 10

这有几个原因.当然,从概念上讲,trySplit可能会回归Optional<Spliterator<T>>,但有一些设计力量已经远离这一点.

一个原因是findFirst返回Optional方法与trySplit返回值 - 或 - null 等方法之间存在差异.

  • 类似findFirst的方法被调用并返回应用程序代码的值.
  • 类似trySplit的方法被调用并返回代码的值.

JDK类库的设计方面是库API(或应该)设计为使应用程序代码更容易,并且库代码通常会更复杂,以使应用程序更简单.

其中一个主要原因Optional是避免将空值从库传递到应用程序代码,因为不正确的空值处理是NullPointerExceptions 的常见来源.相反的null,喜欢的API findFirst将返回一个空的Optional,它是由一组丰富的方法,如支持orElse,map,filter,flatMap,等,为应用程序处理的未发现的情况下提供的灵活性很大.

请注意,可空的返回值来自trySplit相反的方向:从应用程序到库.

将应用程序代码传递给函数库或将可返回的值返回给库,对于应用程序而言,它比从库中接收可为空的值小得多.如果你正在编写的应用程序和API说,你应该通过或空返回到库中,有没有可能性,这将产生在NPE 你的代码.实际上,API中有很多地方(List.sort(null)我想到)API 中null有特定的语义.

trySplit从图书馆中相对较少的地方调用,图书馆维护者承担了null在所有这些情况下妥善处理的负担.

另一个主要考虑因素是表现 拆分是建立并行管道的关键路径.在将工作交给不同的线程并行执行之前,它是按顺序执行的.根据Amdahl定律,为了使并行性尽可能高效,您希望最小化顺序设置开销.

事实是a Optional是一个盒子,装箱和取消装箱的价格是有成本的Optional.在某些情况下,JIT编译器可能能够优化它,但它可能不会.即使它确实存在,也有一段时间代码运行但Optional尚未优化.这是额外的开销.由于库代码愿意承担null正确处理的负担,我们可以保证Optional在这种情况下完全不使用拳击开销.


Tag*_*eev 7

Spliterator是内部流实现的一部分.它不应该用在Optional方便的业务逻辑中.它的低级接口主要目标是快速.所以没有理由Optional.

您可能会争辩说OptionalJIT编译器通常可以消除它.然而,并非总是如此.例如,Hotspot JIT编译器中内联调用的默认最大深度为10,并且通常的流处理具有更多堆栈帧,因此即使一个额外的堆栈帧也可能阻止优化.

  • 通常,`Optional`是由直接调用者打开的,对于`Stream`实现来说没有什么不同,所以其他堆栈帧并不重要. (2认同)