3

I know java streams, and tried to implement the map, filter, fold (with custom function as argument), both the strict and lazy evaluation ways.

However i could not implement a lazy implementation of flatmap in java. Normal map,filter, fold are just composed functions which run on the main iterator (if its list) and apply of functions is discarded if the incoming value is null.

However flatMap input function produces another list( stream) which needs to be flattened,

How is the lazy flatMap implemented in java 10? is there any document on the algorithm?

Thanks.

Naresh B
  • 31
  • 3
  • 1
    This *has* been fixed, but what is your question? How to implement lazy operations in general? Just invoke `tryAdvance` repeatedly until you have your result, instead of running `forEachRemaining`. The actual question should be, why didn’t they do it correctly right in the first version. [This alternative implementation](https://stackoverflow.com/a/32767282/2711488) existed even before Java 10. – Holger Sep 20 '18 at 07:02
  • got it thanks, i was looking at fold and not at findFirst similar which are lazy thanks – Naresh B Sep 27 '18 at 11:47

1 Answers1

0

If you want to implement lazy flatMap, the most important part is to provide a correct implementation of Iterator. This implementation can look like this:

final class FlatMappedIterator<A, B> implements Iterator<B> {
    private final Iterator<A> iterator;
    private final Function<A, Iterable<B>> f;
    private Iterator<B> targetIterator; // Iterator after applying `f` to element of type A

    FlatMappedIterator(Iterator<A> iterator, Function<A, Iterable<B>> f) {
        this.iterator = iterator;
        this.f = f;
    }

    @Override
    public boolean hasNext() {
        if (targetIterator != null && targetIterator.hasNext()) {
            return true;
        } else if (iterator.hasNext()) {
            A next = iterator.next();
            Iterable<B> targetIterable = f.apply(next);
            targetIterator = targetIterable.iterator();
            return targetIterator.hasNext();
        } else {
            return false;
        }
    }

    @Override
    public B next() {
        if (hasNext()) {
            return targetIterator.next();
        } else {
            throw new NoSuchElementException();
        }
    }
}

So the retrieval of the next element is postponed to the moment when hasNext or next is called.

Then you need to implement the flatMap function itself. But this is easy. I'm leaving it as an exercise for the reader :)

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155