4

I know there is infinite stream in Java.

Is there a way to check whether the stream is finite or not?

Something like this method 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();
}

The construction of the Stream would leave some marks/tracks that we can use to trace back to check it?

The checking method could work always as expected reliably?

Update

I was wrong about this when trying to solve a problem by detecting the isFinite of a stream. It seems it's not stable/reliable as the answers mentioned. I will refactor my solution in another around. Thank you for the help ~

Hearen
  • 7,420
  • 4
  • 53
  • 63
  • 6
    c.f. https://en.wikipedia.org/wiki/Halting_problem It's not possible to solve generically. Only determine how the stream was constructed. – Peter Lawrey Jun 25 '18 at 15:19
  • Does your method return? – shmosel Jun 25 '18 at 15:20
  • Hahah, of course no ~ it's just a demo to provide what I am trying to do. – Hearen Jun 25 '18 at 15:21
  • 3
    I *think* that there could have been a flag introduced when it is absolutely known that a certain stream is infinite, like `generate` for example; but what would be the real value in this? And how about `Files.lines` for example, is your file a "finite" one? I can't tell why there would be a need to have this. Also `Long.MAX_VALUE` is reported in numerous other cases too, besides an infinite stream... – Eugene Jun 25 '18 at 15:32

2 Answers2

7

There is no reliable way to do it. Even using the estimateSize, which is documented:

... or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute.

So simply relying on the fact that Long.MAX_VALUE will tell you if this stream is infinite or not - is simply wrong.

The other suggestion says that to use SIZED, which is again wrong:

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

You know that this is a SIZED stream - the implementation does not and will not report the sized flag.

Bottom-line: you can't in a reliable way. Theoretically this could be possible for some cases, like when you just use generate without limiting or short-circuiting the stream, the implementation could register a flag like IS_INFINITE or something, but this IMO would be useless, probably for 99% of the cases.

You can also think in reverse here, how about when you want to tell with certainty if this stream is finite? In such a case, getExactSizeIfKnown() would tell you that.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 3
    And don’t forget, nobody knows whether `IntStream.generate(() -> 1) .takeWhile(x -> externalCondition(x))` is finite… – Holger Jun 25 '18 at 16:20
  • 1
    Well, if there was an `IS_INFINITE` flag, it allowed the implementation to turn the `IntStream.generate(() -> 1).limit(5)` example into a `SIZED` stream. But for external code, it would not have much use as the absence of this flag still doesn’t guaranty that the stream is finite. – Holger Jun 26 '18 at 10:51
  • @Holger It seems it's much more complicated than I thought. I will refactor my solution. Thank you ~ – Hearen Jun 27 '18 at 06:56
2

There is no way to check if a stream is infinite with certainty, but there is a way to detect if it's finite with certainty.

[fixed] I had it the wrong way around.

/**
 * 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;
}

Javadoc of estimateSize():

Returns an estimate of the number of elements that would be encountered by a forEachRemaining traversal, or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute.

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
  • 2
    this is probably the best guess there is, but still just a guess, there is no reliable way to do it – Eugene Jun 25 '18 at 15:25
  • 5
    You can use `getExactSizeIfKnown() >= 0` to detect when it is definitely finite. – Holger Jun 25 '18 at 15:45