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在这种情况下完全不使用拳击开销.
Spliterator是内部流实现的一部分.它不应该用在Optional方便的业务逻辑中.它的低级接口主要目标是快速.所以没有理由Optional.
您可能会争辩说OptionalJIT编译器通常可以消除它.然而,并非总是如此.例如,Hotspot JIT编译器中内联调用的默认最大深度为10,并且通常的流处理具有更多堆栈帧,因此即使一个额外的堆栈帧也可能阻止优化.
| 归档时间: |
|
| 查看次数: |
538 次 |
| 最近记录: |