Expected behavior of a Streams.cycled() instance - found issues and questions

Brian Goetz brian.goetz at oracle.com
Tue Oct 23 10:11:35 PDT 2012

Thanks for the questions.  Bear in mind that most of the methods in 
Streams are experimental.

>    In the current API there is a utility class java.util.streams.Streams
>    which contains besides others method cycled().
>    There are few problems and questions regarding how a properly cycled
> stream should behave
>    in terms of conforming to the standard contract of the Stream interface.
>    Some of the questions apply to any infinite stream.
>    0) (Sorry if this has been discussed already) - is there any legal way
> to get flags of a random Stream instance?

Currently, there is not.  However, we might consider adding a 
getStreamFlags() method on BaseStream.

> 1) Should it be allowed (as it is now) to concat to the end of an
> infinite (cycled for example) stream?

It doesn't seem so useful, but also such attempts to protect the user 
from themselves are also often counterproductive, especially if "known 
infinite" really means "probably infinite."  For example, what about:

   infiniteStream.filter(t -> false)

So the answer is "maybe, but maybe not."

>    2) Getting next element of a flatMap of a cycled stream leads to hanging:
>       Streams.cycle(Arrays.asList(1, 2, 3)).flatMap((Block<Object> sink,
> Integer element) -> {}).iterator().next();

That seems like a bug...

>    3) cycledStream.noneMatch((obj) -> false)) leads to hanging as well
> though it probably should not.
>    4) Getting iterator for a sorted cycled stream leads to
> java.lang.OutOfMemoryError: Java heap space
>       Streams.cycle(Arrays.asList(1, 2,
> 3)).sorted(Comparators.<Integer>reverseOrder()).iterator();

Yes, this is expected -- sorting an infinite stream takes infinite time 
and space.  Its a fair question as to how far we should go to protect 
the user from this.  Users can create infinite loops now; we trust them 
to know whether they terminate.

>    5) cycledStream.uniqueElements() leads to IllegalStateException though
> it should not according to common sense.

Well, I'm not sure I agree with the notion of common sense here; I think 
its a bit much to ask the runtime to do this kind of analysis.  But this 
is a fine example of the sort of trouble we get in when we do try and 
protect the user from themselves; this ISE is exactly what you're asking 
for in (1), and we should probably remove it.

>    6) This will lead to hanging:
>       Streams.cycle(Arrays.asList(1, 2, 3)).filter((obj) ->
> false).iterator().hasNext();
>    7) This will lead to hanging as well:
>       Streams.cycle(Arrays.asList(1, 2, 3)).allMatch((obj) -> true);
>    8) And this hangs up also:
>       Streams.cycle(Arrays.asList(1, 2, 3)).anyMatch((obj) -> false);

Yes.  I think these are reasonable.

More information about the lambda-dev mailing list