为什么在Java Stream接口中重载()的varargs方法?

时间:2016-03-04 17:24:37

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

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

单参数方法是一种性能优化,而不是将一个参数传递给variable-arity方法?如果是这样,它如何提高性能?可以询问empty()方法的相同问题,这似乎是变量ar of()周围的语法糖。

我看到这些方法的实现方式不同,显然差异在于Spliterator的实例化方式;但这对Stream API有什么好处?

3 个答案:

答案 0 :(得分:6)

空流和单个元素流是非常常见的用例,尤其是当您使用.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()不会创建空数组,也不会创建spliterator(它会重用相同的spliterator实例)。 Stream.of(T)内部StreamBuilderImpl也得到了特别优化,因此没有为单个元素分配数组。

答案 1 :(得分:5)

是的,它是一种优化,可以避免创建一个只包含单个元素的数组的开销,这是您使用varargs版本时所获得的。

  

可以询问empty()方法的相同问题,这似乎是()

的变量范围内的语法糖

您正在查看哪种实施版本?当我看到实施时,我不明白这一点。

答案 2 :(得分:1)

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

  

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

     

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

因此,性能优化非常简单,以避免使用varargs方法的数组。