有没有一种方法可以检查Java流是否有限?

时间:2018-06-25 15:12:04

标签: java java-8 java-stream

我知道Java中存在无限流。

是否可以检查流是否有限?

类似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();
}

的构造会留下一些标记/轨道,我们可以使用它们来追溯以进行检查?

检查方法是否可以始终可靠地按预期工作?

更新

在尝试通过检测流的isFinite解决问题时,我对此有误。所提到的答案似乎并不稳定/可靠。我将在其他地方重构我的解决方案。谢谢你的帮助〜

2 个答案:

答案 0 :(得分:7)

没有可靠的方法来做到这一点。甚至使用estimateSize,该文件已记录在案:

  

...,如果无限,未知或计算成本过高,则返回Long.MAX_VALUE。

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

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

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

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

底线:您无法以可靠的方式。从理论上讲,在某些情况下这是可能的,例如当您使用generate而没有限制或短路流时,实现可以注册一个IS_INFINITE之类的标志,但是此IMO可能毫无用处,可能在99%的情况下都是如此。

您在这里也可以反过来思考,如果您想确定地确定此流是否有限,该怎么办?在这种情况下,getExactSizeIfKnown()会告诉您。

答案 1 :(得分: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