0

When I run the following code:

    Stream.of("a", "b", "c")
        .flatMap(s -> Stream.of(s, s+s))
        .map(s -> {System.out.printf("complex operation on %s\n", s); return s;})
        .findFirst()
        .ifPresent(s -> System.out.printf("outcome %s\n", s));

...the map operation runs for the first two elements in the stream, instead of just the first one:

complex operation on a
complex operation on aa
outcome a

However, if I explicitly collect after the flatMap:

    Stream.of("a", "b", "c")
        .flatMap(s -> Stream.of(s, s + s))
        .collect(Collectors.toList())
        .stream()
        .map(s -> {System.out.printf("complex operation on %s\n", s); return s;})
        .findFirst()
        .ifPresent(s -> System.out.printf("outcome %s\n", s));

...then the map operation runs on only the first element, as I'd expect.

Why is there a difference, and how can I can I get the map to only process the first item without collecting the whole incoming stream?

Please note that this is not my actual code. In practice I need to filter after the map and before the findFirst, so I can't do something like call findFirst before map.

I also tried:

  • .sequential() after the flatMap (no effect)
  • .sorted() after the flatMap (works, but reads the whole stream, and in my real application it doesn't actually make sense to sort)
  • 1
    First time i have seen question ,flag , answer by same person ;). – soorapadman Aug 29 '18 at 05:40
  • Collections are not lazy. By asking to create a collection, you are explicitly telling it to be fully evaluated before continuing. A stream is already sequential() by default. `sorted()` has to collect all element to find the smallest one. There is no way around this without knowledge of what the minimum values are. – Peter Lawrey Aug 29 '18 at 07:12

1 Answers1

0

It looks like the answer to the root cause is also here: Why filter() after flatMap() is "not completely" lazy in Java streams?

Apparently it's a known bug that will be fixed in Java 10. See JDK-8075939.