0

Given this code:

@Test
public void test() throws Exception
{
    Iterator<Integer> iterator = Stream
        .of(0, 2)
        .flatMap(x -> Stream.of(x, x + 1))
        .map(element -> {
            System.out.println("Stream generating element: " + element);
            return element;
        })
        .iterator();

    while (iterator.hasNext())
    {
        Integer value = iterator.next();
        System.out.println("Iterated value: " + value);
    }
}

What I expected to see:

Stream generating element: 0
Iterated value: 0
Stream generating element: 1
Iterated value: 1
Stream generating element: 2
Iterated value: 2
Stream generating element: 3
Iterated value: 3

What I actually see:

Stream generating element: 0
Stream generating element: 1
Iterated value: 0
Iterated value: 1
Stream generating element: 2
Stream generating element: 3
Iterated value: 2
Iterated value: 3

We had been relying on Stream#iterator() returning a lazy iterator, but it seems that in some situations, such as this one, it walks more elements than you have asked for. This is catastrophic if, for example, retrieving the next element requires making a multicast DNS request, which would take 6 seconds to come back.

Is there a way to avoid this and get a truly lazy iterator without implementing my own iterator manually somehow (something which I'm not entirely sure how to even do)?

Hakanai
  • 12,010
  • 10
  • 62
  • 132
  • You honestly shouldn't be using streams *or* iterators for that use case. They're really for on heap data, things that can't fail. – Louis Wasserman Aug 14 '17 at 05:38
  • At some point the caller is going to want to iterate it... – Hakanai Aug 14 '17 at 06:48
  • Not necessarily with an Iterator. Give them an API that can ask for a next element, specify a deadline, throw an exception. – Louis Wasserman Aug 14 '17 at 16:05
  • You'd have to be careful that the exception indicates whether it's worth calling next() again, or mix error objects with result objects, or wrap the objects in something containing both... somehow it seems like it would be easier to use if it allowed using normal iteration from the caller. mDNS libraries don't hand us back errors anyway, unless there is something truly catastrophic, like the machine not having any network adapters, and even then it might just return immediately with no error. :/ In any case, though, that was just one example of using streams. – Hakanai Aug 15 '17 at 23:16

0 Answers0