Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8075939

Stream.flatMap() causes breaking of short-circuiting of terminal operations

    XMLWordPrintable

Details

    Backports

      Description

        FULL PRODUCT VERSION :
        java version "1.8.0_40"
        Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
        Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Linux smobile 3.16.0-33-generic #44-Ubuntu SMP Thu Mar 12 12:19:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

        A DESCRIPTION OF THE PROBLEM :
        Terminal short-circuit operations behave differently when called on stream produced by flatMap comparing to stream generated without involving flatMap.

        Stream.of(1, 2, 3).filter(i -> { System.out.println(i); return true; }).findFirst() as expected will print single element of the stream, namely '1', as findFirst terminates once first element is produced (sequential stream case).
        Unlike this,
        Stream.of(1, 2, 3).flatMap(i -> Stream.of(i - 1, i, i + 1)).flatMap(i -> Stream.of(i - 1, i, i + 1)).filter(i -> { System.out.println(i); return true; }).findFirst()
        will print 9 stream element which correspond to flattened stream corresponding to first element of source stream despite it is not needed for findFirst().
        In case of finite stream, it is just inefficiency. However, if flatMap function produces infinite stream it will cause findFirst() never return which seems to be breaking short-circuiting behaviour of terminal operations on the stream.

        From docs: "An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result."
        "findFirst()
        ...
        This is a short-circuiting terminal operation."

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        System.out.println("Infinite result: " +
                                Stream.of(0).flatMap(x->Stream.iterate(0, i->i+1)).findFirst());

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Infinite result: 0
        ACTUAL -
        It never prints anything as fails to unwind infinite stream.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
                System.out.println(
                        "Correct Result: " +
                        Stream.of(1, 2, 3)
                                .filter(i -> {
                                    System.out.println(i);
                                    return true;
                                })
                                .findFirst()
                                .get()
                );
                System.out.println("-----------");
                System.out.println(
                        "Correct Result with unnecessary filtering: " +
                        Stream.of(1, 2, 3)
                                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                                .filter(i -> {
                                    System.out.println(i);
                                    return true;
                                })
                                .findFirst()
                                .get()
                );

                System.out.println("Result is never printed: " +
                                Stream.of(0).flatMap(x->Stream.iterate(0, i->i+1)).findFirst());
        ---------- END SOURCE ----------

        Attachments

          Issue Links

            Activity

              People

                psandoz Paul Sandoz
                webbuggrp Webbug Group
                Votes:
                1 Vote for this issue
                Watchers:
                8 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved: