【问题标题】:Why overload the varargs method of() in Java Stream interface?为什么要在 Java Stream 接口中重载 varargs 方法 of()?
【发布时间】:2016-06-18 13:19:55
【问题描述】:

Stream 接口对方法of() 有两个重载。其中一个是可变参数方法,而另一个采用单个参数。

与将一个参数传递给可变参数方法相比,单参数方法是一种性能优化吗?如果是这样,它如何提高性能?可以对 empty() 方法提出相同的问题,这似乎是可变参数 of() 周围的语法糖。

我看到这些方法之间的实现有所不同,区别显然在于Spliterator 的实例化方式;但是这对Stream API 有什么好处呢?

【问题讨论】:

    标签: java overloading java-stream variadic-functions spliterator


    【解决方案1】:

    我偶然发现了一个官方资源,它证实了这个问题的先前答案:JEP 269: Convenience Factory Methods for Collections。该提案的描述是,

    ListSetMap 接口上提供静态工厂方法,用于创建这些集合的不可修改实例。

    这些将包括可变参数重载,因此对集合大小没有固定限制...将提供最多十个元素的特殊情况 API(固定参数重载)。虽然这会在 API 中引入一些混乱,但它避免了由 varargs 调用引起的数组分配、初始化和垃圾收集开销。

    所以性能优化很简单,就是避免使用 varargs 方法的数组。

    【讨论】:

      【解决方案2】:

      空流和单元素流是非常常见的用例,尤其是当您使用.flatMap() 时。例如,在 Java-9 中 Optional.stream()implemented

      public Stream<T> stream() {
          if (!isPresent()) {
              return Stream.empty();
          } else {
              return Stream.of(value);
          }
      }
      

      因此,鉴于 Optionals 的流,您可以通过这种方式将它们展开到平面流中:

      streamOfOptionals.flatMap(Optional::stream);
      

      在这里,您创建了大量的空流以及单元素流,因此优化此类情况看起来非常合理。特别是,Stream.empty()Stream.of() 不同,它不会创建空数组,也不会创建拆分器(它重用相同的拆分器实例)。 Stream.of(T)StreamBuilderImpl 内部也进行了特别优化,因此没有为单个元素分配数组。

      【讨论】:

        【解决方案3】:

        是的,这是一种优化,可以避免创建一个仅包含单个元素的数组的开销,如果您使用可变参数版本,您会得到这样的结果。

        empty() 方法也可以问同样的问题,这似乎是围绕可变参数 of() 的语法糖

        您在看什么实施版本?当我查看实现时,我看不到这一点。

        【讨论】:

        • 我的意思只是方法签名似乎表明语法糖(并且文档没有指出一种或另一种方式)。我看到实现方式不同。
        • 避免单个元素或空数组似乎是一种微优化。这是普通开发人员应该关心的事情吗?我应该为我的所有可变参数方法提供这种类型的性能优化吗?
        • @jaco0646,语法糖有什么问题?特别是如果它还提供性能优化机会。
        • @jaco0646 您是否正在编写一个与java.util.stream.Stream 一样广泛使用的 API?如果没有,那么可能不值得担心。
        猜你喜欢
        • 2018-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-22
        • 2015-11-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多