【问题标题】:Would a singleton Stream.empty make sense?单例 Stream.empty 有意义吗?
【发布时间】:2020-03-19 19:19:21
【问题描述】:

对我当前的应用程序进行一些分析,顶部分配是对 Stream.empty() 的过度调用,这反过来又分配了一个 new ReferencePipeline.Head<> 导致大量虚假对象。

这让我想到,Stream.empty() 为什么不简单地返回一个特殊的可重用单例流,而不是每次都分配新的流? 这是个好主意吗?如果是这样,是否有任何库/示例已经这样做了?

【问题讨论】:

  • 如果这是一个非常好的想法,它可能会被实施。 JDK 中有Collections.emptyXXX() 等,所以它肯定在JDK 开发人员的工具箱中。缺乏不变性可能会阻止该方法与流一起使用。但是我(傲慢地)质疑这是否是一个实际问题。如果Stream.empty() 是内存热点,您的应用程序会做什么?
  • 嗯,Collections.empty 正是让我想到的。
  • 请注意,flatMap 允许返回 null 以表示空流。这可以防止过多创建空流实例。在flatMap 之外,这几乎不是问题。

标签: java performance java-stream


【解决方案1】:

与空集合不同,流是可变的,甚至是空流。

例如,Stream 具有更改其状态的 close() 方法。 specification 要求这样做

在关闭后对流进行操作会抛出 IllegalStateException。

上面也说了

应该对流进行操作(调用中间或终端 流操作)只有一次。例如,这排除了“分叉” 流,其中相同的源为两个或多个管道或 同一流的多次遍历。流实现可以 如果检测到流正在被抛出,则抛出 IllegalStateException 重复使用。

这意味着缓存流的实例没有意义,因为无论如何都不能重用流。

【讨论】:

  • 由于检测重用不是强制性的,因此实现可以使用缓存的空流而不是重用作为实现细节。但是onClose+close 的存在阻止了这一点。
【解决方案2】:

Stream.empty()的Java 8版本如下。

public static<T> Stream<T> empty() {
    return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);
}

StreamSupport

public static <T> Spliterator<T> emptySpliterator() {
    return (Spliterator<T>) EMPTY_SPLITERATOR;
}

private static final Spliterator<Object> EMPTY_SPLITERATOR =
        new EmptySpliterator.OfRef<>();

因此,虽然他们没有重用空流,但他们重用了空的 Spliterator,从而在对象分配中节省了一点。

【讨论】:

    猜你喜欢
    • 2014-11-27
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2014-08-07
    • 2020-12-05
    相关资源
    最近更新 更多