【问题标题】:Is there a way to check whether a stream is finite in Java? [closed]有没有办法检查Java中的流是否有限? [关闭]
【发布时间】:2018-06-25 15:12:03
【问题描述】:

我知道 Java 中有 infinite 流。

有没有办法检查流是否有限?

类似这种方法isStreamFinite(Stream<T> stream)?

@Test
public void testStreamFinity() {
    assertFalse(isStreamFinite(generateLong()));
}

private <T> boolean isStreamFinite(Stream<T> stream) {
    if (stream.count() < Long.MAX_VALUE) {
        return true;
    }
    return false;
}

private Stream<Long> generateLong() {
    return LongStream.generate(() -> new Random().nextLong()).boxed();
}

Stream 的构造会留下一些标记/轨迹,我们可以用来追溯检查它吗?

检查方法能否始终如期可靠地工作?

更新

当我试图通过检测流的isFinite 来解决问题时,我错了。正如上面提到的答案,它似乎不稳定/可靠。我将在另一个周围重构我的解决方案。谢谢你的帮助~

【问题讨论】:

  • c.f. en.wikipedia.org/wiki/Halting_problem 一般无法解决。只确定流是如何构造的。
  • 你的方法返回了吗?
  • 哈哈,当然不是~这只是一个演示,提供我正在尝试做的事情。
  • 认为当绝对知道某个流是无限的时可能会引入一个标志,例如generate;但这真正的价值是什么?例如,Files.lines 怎么样,您的文件是“有限”文件吗?我不知道为什么需要这个。除了无限流之外,Long.MAX_VALUE 在许多其他情况下也有报道......

标签: java java-8 java-stream


【解决方案1】:

没有可靠的方法来做到这一点。即使使用记录在案的estimateSize

...如果无限、未知或计算过于昂贵,则返回 Long.MAX_VALUE。

因此,仅仅依靠Long.MAX_VALUE 会告诉你这个流是否是无限的这一事实是完全错误的。

另一个建议是使用SIZED,这又是错误的:

IntStream.generate(() -> 1).limit(5)

知道这是一个SIZED 流 - 实现不会也将不会报告大小标志。

底线:你不能以可靠的方式。理论上这在某些情况下是可能的,例如当您使用generate而不限制或短路流时,实现可以注册像IS_INFINITE这样的标志,但这个IMO会无用,可能在 99% 的情况下。

你也可以在这里反过来想,当你想确定这个流是否是有限的时候怎么样?在这种情况下,getExactSizeIfKnown() 会告诉你。

【讨论】:

  • 别忘了,没有人知道IntStream.generate(() -&gt; 1) .takeWhile(x -&gt; externalCondition(x)) 是否是有限的……
  • 好吧,如果有一个IS_INFINITE 标志,它允许实现将IntStream.generate(() -&gt; 1).limit(5) 示例转换为SIZED 流。但是对于外部代码,它没有多大用处,因为没有这个标志仍然不能保证流是有限的。
  • @Holger 这似乎比我想象的要复杂得多。我将重构我的解决方案。谢谢~
【解决方案2】:

没有办法确定流是否是无限的,但是有办法确定它是否是有限的。

[已修复] 我弄错了。

/**
 * When this returns {@code true}, the stream is finite for sure. Otherwise the
 * stream could be either infinite or finite.
 */
private static <T> boolean isStreamFinite(Stream<T> stream) {
    return stream.spliterator().estimateSize() != Long.MAX_VALUE;
}

estimateSize()的Javadoc:

返回 forEachRemaining 遍历将遇到的元素数量的估计值,如果无限、未知或计算过于昂贵,则返回 Long.MAX_VALUE

【讨论】:

  • 这可能是最好的猜测,但仍然只是猜测,没有可靠的方法来做到这一点
  • 您可以使用getExactSizeIfKnown() &gt;= 0 来检测它何时肯定是有限的。
猜你喜欢
  • 1970-01-01
  • 2020-01-07
  • 2022-06-10
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-02
  • 1970-01-01
相关资源
最近更新 更多