【问题标题】:Spliterator trySplit return type拆分器 trySplit 返回类型
【发布时间】:2015-07-23 13:06:26
【问题描述】:

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

方法 trySplit() 应该返回 Spliterator 或 null 的实例,如果它不能被拆分的话。 Java 文档说明如下:

 * @return a {@code Spliterator} covering some portion of the
 * elements, or {@code null} if this spliterator cannot be split.

在我看来,这是使用java.util.Optional 的理想场所。根据 javadoc:

 * A container object which may or may not contain a non-null value.

有什么原因,为什么没有使用Optional?

谷歌搜索并没有多大帮助,除了 lambda-dev 邮件列表中的 question 没有得到答复。

【问题讨论】:

    标签: java lambda java-8 spliterator


    【解决方案1】:

    之所以如此,有几个原因。当然,从概念上讲,trySplit 可以返回 Optional<Spliterator<T>>,但有一些设计力量推动了这一点。

    一个原因是返回 Optional 的方法(如 findFirst)与返回值或 null 的方法(如 trySplit)之间存在差异。

    • 像findFirst 这样的方法被应用程序代码调用并返回值。
    • trySplit 之类的方法被 library 代码调用并返回值。

    JDK 类库的一个设计方面是库 API 旨在(或应该)使应用程序代码更容易,而库代码通常会变得更复杂,以使应用程序更简单。

    Optional 的主要原因之一是避免将空值从库传递到应用程序代码,因为不正确的空值处理是 NullPointerExceptions 的常见来源。而不是null,像findFirst 这样的API 将返回一个空的Optional,它由一组丰富的方法支持,如orElse、map、filter、flatMap 等提供处理未找到案例的应用程序具有很大的灵活性。

    请注意,来自trySplit 的可为空返回值正朝着相反的方向发展:从应用程序到库。

    让应用程序代码向库传递或返回一个可为空值的应用程序比让应用程序从库接收一个可为空的值更不容易出错。如果您正在编写应用程序并且 API 说您应该向库传递或返回 null,那么这不可能在 您的 代码中生成 NPE。实际上,API 中有很多地方(想到了List.sort(null))null 在 API 中具有特定的语义。

    trySplit 在库中相对较少的地方被调用,并且库维护人员正在承担在所有这些情况下正确处理 null 的责任。

    另一个主要考虑因素是性能。拆分是建立并行管道的关键路径。它是按顺序执行的,然后将工作移交给不同的线程以并行执行。根据Amdahl's Law,为了使并行性尽可能高效,您希望最大限度地减少顺序设置开销。

    事实上,Optional 是一个盒子,在 Optional 之间装箱和拆箱是有成本的。 JIT 编译器可能在某些情况下能够优化这一点,但它可能不会。即使是这样,也有一段时间代码正在运行,但 Optional 还没有被优化掉。这是额外的开销。由于库代码愿意承担正确处理null 的负担,我们可以保证在这种情况下根本不使用Optional 就不会产生装箱开销。

    【讨论】:

      【解决方案2】:

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

      您可能会争辩说,Optional 通常可以被 JIT 编译器消除。然而,情况并非总是如此。例如,Hotspot JIT 编译器中内联调用的默认最大深度为 10,而通常的流处理具有更多的堆栈帧,因此即使增加一个堆栈帧也可能会妨碍优化。

      【讨论】:

      • 通常Optional 被直接调用者解包,这对于Stream 实现来说并没有什么不同,因此其他堆栈帧并不重要。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 2023-04-01
      • 2017-12-16
      • 2021-03-11
      • 2016-09-15
      • 1970-01-01
      相关资源
      最近更新 更多