Considering list elements that are added after filtered stream creation












9














Given the following code:



List<String> strList = new ArrayList<>();
strList.add("Java");
strList.add("Python");
strList.add("Php");

Stream<String> strStream = strList.stream();

Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));

strList.add("JavaScript"); // element added after filter creation
strList.add("JQuery"); // element added after filter creation

System.out.println(Arrays.toString(jFilter.toArray()));


which outputs:



[Java, JavaScript, JQuery]


Why do JavaScript and JQuery appear in the filtered result even though they were added after creating the filtered stream?










share|improve this question





























    9














    Given the following code:



    List<String> strList = new ArrayList<>();
    strList.add("Java");
    strList.add("Python");
    strList.add("Php");

    Stream<String> strStream = strList.stream();

    Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));

    strList.add("JavaScript"); // element added after filter creation
    strList.add("JQuery"); // element added after filter creation

    System.out.println(Arrays.toString(jFilter.toArray()));


    which outputs:



    [Java, JavaScript, JQuery]


    Why do JavaScript and JQuery appear in the filtered result even though they were added after creating the filtered stream?










    share|improve this question



























      9












      9








      9


      1





      Given the following code:



      List<String> strList = new ArrayList<>();
      strList.add("Java");
      strList.add("Python");
      strList.add("Php");

      Stream<String> strStream = strList.stream();

      Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));

      strList.add("JavaScript"); // element added after filter creation
      strList.add("JQuery"); // element added after filter creation

      System.out.println(Arrays.toString(jFilter.toArray()));


      which outputs:



      [Java, JavaScript, JQuery]


      Why do JavaScript and JQuery appear in the filtered result even though they were added after creating the filtered stream?










      share|improve this question















      Given the following code:



      List<String> strList = new ArrayList<>();
      strList.add("Java");
      strList.add("Python");
      strList.add("Php");

      Stream<String> strStream = strList.stream();

      Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));

      strList.add("JavaScript"); // element added after filter creation
      strList.add("JQuery"); // element added after filter creation

      System.out.println(Arrays.toString(jFilter.toArray()));


      which outputs:



      [Java, JavaScript, JQuery]


      Why do JavaScript and JQuery appear in the filtered result even though they were added after creating the filtered stream?







      java java-8 java-stream






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 17 mins ago









      Didier L

      7,68823166




      7,68823166










      asked 10 hours ago









      mmuzahid

      1,4691228




      1,4691228
























          5 Answers
          5






          active

          oldest

          votes


















          6














          Short Answer



          You're assuming after this point:



          Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));


          That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;



          streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.



          The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].



          Longer Answer



          here's part of the documentation which mentions this:




          For well-behaved stream sources, the source can be modified before
          the terminal operation commences and those modifications will be
          reflected in the covered elements. For example, consider the following
          code:



           List<String> l = new ArrayList(Arrays.asList("one", "two"));
          Stream<String> sl = l.stream();
          l.add("three");
          String s = sl.collect(joining(" "));


          First a list is created consisting of two strings: "one"; and "two". Then a stream is created
          from that list. Next the list is modified by adding a third string:
          "three". Finally the elements of the stream are collected and joined
          together. Since the list was modified before the terminal collect
          operation commenced the result will be a string of "one two three".
          All the streams returned from JDK collections, and most other JDK
          classes, are well-behaved in this manner;







          share|improve this answer































            6














            Until the statement



            System.out.println(Arrays.toString(jFilter.toArray()));


            runs, the stream doesn't do anything. A terminal operation (toArray in the example) is required for the stream to be traversed and your intermediate operations (filter in this case) to be executed.



            In this case, what you can do is, for example, capture the size of the list before adding other elements:



            int maxSize = strList.size();
            Stream<String> jFilter = strStream.limit(maxSize)
            .filter(str -> str.startsWith("J"));


            where limit(maxSize) will not allow more than the initial elements to go through the pipeline.






            share|improve this answer































              3














              Its because the stream never got evaluated. you never called a "Terminal operation" on that stream for it to get executed as they're lazy.



              Look at a modification of your code and the output. The filtering actually takes place when you call the Terminal Operator.



               public static void main(String args){
              List<String> strList = new ArrayList<>();
              strList.add("Java");
              strList.add("Python");
              strList.add("Php");

              Stream<String> strStream = strList.stream();

              Stream<String> jFilter = strStream.filter(str -> {
              System.out.println("Filtering" + str);
              return str.startsWith("J");
              });

              System.out.println("After Stream creation");
              strList.add("JavaScript"); // element added after filter creation
              strList.add("JQuery"); // element added after filter creation

              System.out.println(Arrays.toString(jFilter.toArray()));

              }


              Output:



              After Stream creation
              FilteringJava
              FilteringPython
              FilteringPhp
              FilteringJavaScript
              FilteringJQuery
              [Java, JavaScript, JQuery]





              share|improve this answer





























                1














                As explained in the official documentation at ,https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html, streams have no storage, and so are more like iterators than collections, and are evaluated lazily.



                So, nothing really happens with respect to the stream until you invoke the terminal operation toArray()






                share|improve this answer





























                  1














                  @Hadi J's comment but it should be answer according to the rules.




                  Because streams are lazy and when you call terminal operation it executed.







                  share|improve this answer





















                    Your Answer






                    StackExchange.ifUsing("editor", function () {
                    StackExchange.using("externalEditor", function () {
                    StackExchange.using("snippets", function () {
                    StackExchange.snippets.init();
                    });
                    });
                    }, "code-snippets");

                    StackExchange.ready(function() {
                    var channelOptions = {
                    tags: "".split(" "),
                    id: "1"
                    };
                    initTagRenderer("".split(" "), "".split(" "), channelOptions);

                    StackExchange.using("externalEditor", function() {
                    // Have to fire editor after snippets, if snippets enabled
                    if (StackExchange.settings.snippets.snippetsEnabled) {
                    StackExchange.using("snippets", function() {
                    createEditor();
                    });
                    }
                    else {
                    createEditor();
                    }
                    });

                    function createEditor() {
                    StackExchange.prepareEditor({
                    heartbeatType: 'answer',
                    autoActivateHeartbeat: false,
                    convertImagesToLinks: true,
                    noModals: true,
                    showLowRepImageUploadWarning: true,
                    reputationToPostImages: 10,
                    bindNavPrevention: true,
                    postfix: "",
                    imageUploader: {
                    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                    allowUrls: true
                    },
                    onDemand: true,
                    discardSelector: ".discard-answer"
                    ,immediatelyShowMarkdownHelp:true
                    });


                    }
                    });














                    draft saved

                    draft discarded


















                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53896175%2fconsidering-list-elements-that-are-added-after-filtered-stream-creation%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown

























                    5 Answers
                    5






                    active

                    oldest

                    votes








                    5 Answers
                    5






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    6














                    Short Answer



                    You're assuming after this point:



                    Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));


                    That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;



                    streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.



                    The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].



                    Longer Answer



                    here's part of the documentation which mentions this:




                    For well-behaved stream sources, the source can be modified before
                    the terminal operation commences and those modifications will be
                    reflected in the covered elements. For example, consider the following
                    code:



                     List<String> l = new ArrayList(Arrays.asList("one", "two"));
                    Stream<String> sl = l.stream();
                    l.add("three");
                    String s = sl.collect(joining(" "));


                    First a list is created consisting of two strings: "one"; and "two". Then a stream is created
                    from that list. Next the list is modified by adding a third string:
                    "three". Finally the elements of the stream are collected and joined
                    together. Since the list was modified before the terminal collect
                    operation commenced the result will be a string of "one two three".
                    All the streams returned from JDK collections, and most other JDK
                    classes, are well-behaved in this manner;







                    share|improve this answer




























                      6














                      Short Answer



                      You're assuming after this point:



                      Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));


                      That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;



                      streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.



                      The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].



                      Longer Answer



                      here's part of the documentation which mentions this:




                      For well-behaved stream sources, the source can be modified before
                      the terminal operation commences and those modifications will be
                      reflected in the covered elements. For example, consider the following
                      code:



                       List<String> l = new ArrayList(Arrays.asList("one", "two"));
                      Stream<String> sl = l.stream();
                      l.add("three");
                      String s = sl.collect(joining(" "));


                      First a list is created consisting of two strings: "one"; and "two". Then a stream is created
                      from that list. Next the list is modified by adding a third string:
                      "three". Finally the elements of the stream are collected and joined
                      together. Since the list was modified before the terminal collect
                      operation commenced the result will be a string of "one two three".
                      All the streams returned from JDK collections, and most other JDK
                      classes, are well-behaved in this manner;







                      share|improve this answer


























                        6












                        6








                        6






                        Short Answer



                        You're assuming after this point:



                        Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));


                        That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;



                        streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.



                        The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].



                        Longer Answer



                        here's part of the documentation which mentions this:




                        For well-behaved stream sources, the source can be modified before
                        the terminal operation commences and those modifications will be
                        reflected in the covered elements. For example, consider the following
                        code:



                         List<String> l = new ArrayList(Arrays.asList("one", "two"));
                        Stream<String> sl = l.stream();
                        l.add("three");
                        String s = sl.collect(joining(" "));


                        First a list is created consisting of two strings: "one"; and "two". Then a stream is created
                        from that list. Next the list is modified by adding a third string:
                        "three". Finally the elements of the stream are collected and joined
                        together. Since the list was modified before the terminal collect
                        operation commenced the result will be a string of "one two three".
                        All the streams returned from JDK collections, and most other JDK
                        classes, are well-behaved in this manner;







                        share|improve this answer














                        Short Answer



                        You're assuming after this point:



                        Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));


                        That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;



                        streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.



                        The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].



                        Longer Answer



                        here's part of the documentation which mentions this:




                        For well-behaved stream sources, the source can be modified before
                        the terminal operation commences and those modifications will be
                        reflected in the covered elements. For example, consider the following
                        code:



                         List<String> l = new ArrayList(Arrays.asList("one", "two"));
                        Stream<String> sl = l.stream();
                        l.add("three");
                        String s = sl.collect(joining(" "));


                        First a list is created consisting of two strings: "one"; and "two". Then a stream is created
                        from that list. Next the list is modified by adding a third string:
                        "three". Finally the elements of the stream are collected and joined
                        together. Since the list was modified before the terminal collect
                        operation commenced the result will be a string of "one two three".
                        All the streams returned from JDK collections, and most other JDK
                        classes, are well-behaved in this manner;








                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited 10 hours ago

























                        answered 10 hours ago









                        Aomine

                        37.8k73264




                        37.8k73264

























                            6














                            Until the statement



                            System.out.println(Arrays.toString(jFilter.toArray()));


                            runs, the stream doesn't do anything. A terminal operation (toArray in the example) is required for the stream to be traversed and your intermediate operations (filter in this case) to be executed.



                            In this case, what you can do is, for example, capture the size of the list before adding other elements:



                            int maxSize = strList.size();
                            Stream<String> jFilter = strStream.limit(maxSize)
                            .filter(str -> str.startsWith("J"));


                            where limit(maxSize) will not allow more than the initial elements to go through the pipeline.






                            share|improve this answer




























                              6














                              Until the statement



                              System.out.println(Arrays.toString(jFilter.toArray()));


                              runs, the stream doesn't do anything. A terminal operation (toArray in the example) is required for the stream to be traversed and your intermediate operations (filter in this case) to be executed.



                              In this case, what you can do is, for example, capture the size of the list before adding other elements:



                              int maxSize = strList.size();
                              Stream<String> jFilter = strStream.limit(maxSize)
                              .filter(str -> str.startsWith("J"));


                              where limit(maxSize) will not allow more than the initial elements to go through the pipeline.






                              share|improve this answer


























                                6












                                6








                                6






                                Until the statement



                                System.out.println(Arrays.toString(jFilter.toArray()));


                                runs, the stream doesn't do anything. A terminal operation (toArray in the example) is required for the stream to be traversed and your intermediate operations (filter in this case) to be executed.



                                In this case, what you can do is, for example, capture the size of the list before adding other elements:



                                int maxSize = strList.size();
                                Stream<String> jFilter = strStream.limit(maxSize)
                                .filter(str -> str.startsWith("J"));


                                where limit(maxSize) will not allow more than the initial elements to go through the pipeline.






                                share|improve this answer














                                Until the statement



                                System.out.println(Arrays.toString(jFilter.toArray()));


                                runs, the stream doesn't do anything. A terminal operation (toArray in the example) is required for the stream to be traversed and your intermediate operations (filter in this case) to be executed.



                                In this case, what you can do is, for example, capture the size of the list before adding other elements:



                                int maxSize = strList.size();
                                Stream<String> jFilter = strStream.limit(maxSize)
                                .filter(str -> str.startsWith("J"));


                                where limit(maxSize) will not allow more than the initial elements to go through the pipeline.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited 10 hours ago









                                nullpointer

                                40.1k1074150




                                40.1k1074150










                                answered 10 hours ago









                                ernest_k

                                19.4k41941




                                19.4k41941























                                    3














                                    Its because the stream never got evaluated. you never called a "Terminal operation" on that stream for it to get executed as they're lazy.



                                    Look at a modification of your code and the output. The filtering actually takes place when you call the Terminal Operator.



                                     public static void main(String args){
                                    List<String> strList = new ArrayList<>();
                                    strList.add("Java");
                                    strList.add("Python");
                                    strList.add("Php");

                                    Stream<String> strStream = strList.stream();

                                    Stream<String> jFilter = strStream.filter(str -> {
                                    System.out.println("Filtering" + str);
                                    return str.startsWith("J");
                                    });

                                    System.out.println("After Stream creation");
                                    strList.add("JavaScript"); // element added after filter creation
                                    strList.add("JQuery"); // element added after filter creation

                                    System.out.println(Arrays.toString(jFilter.toArray()));

                                    }


                                    Output:



                                    After Stream creation
                                    FilteringJava
                                    FilteringPython
                                    FilteringPhp
                                    FilteringJavaScript
                                    FilteringJQuery
                                    [Java, JavaScript, JQuery]





                                    share|improve this answer


























                                      3














                                      Its because the stream never got evaluated. you never called a "Terminal operation" on that stream for it to get executed as they're lazy.



                                      Look at a modification of your code and the output. The filtering actually takes place when you call the Terminal Operator.



                                       public static void main(String args){
                                      List<String> strList = new ArrayList<>();
                                      strList.add("Java");
                                      strList.add("Python");
                                      strList.add("Php");

                                      Stream<String> strStream = strList.stream();

                                      Stream<String> jFilter = strStream.filter(str -> {
                                      System.out.println("Filtering" + str);
                                      return str.startsWith("J");
                                      });

                                      System.out.println("After Stream creation");
                                      strList.add("JavaScript"); // element added after filter creation
                                      strList.add("JQuery"); // element added after filter creation

                                      System.out.println(Arrays.toString(jFilter.toArray()));

                                      }


                                      Output:



                                      After Stream creation
                                      FilteringJava
                                      FilteringPython
                                      FilteringPhp
                                      FilteringJavaScript
                                      FilteringJQuery
                                      [Java, JavaScript, JQuery]





                                      share|improve this answer
























                                        3












                                        3








                                        3






                                        Its because the stream never got evaluated. you never called a "Terminal operation" on that stream for it to get executed as they're lazy.



                                        Look at a modification of your code and the output. The filtering actually takes place when you call the Terminal Operator.



                                         public static void main(String args){
                                        List<String> strList = new ArrayList<>();
                                        strList.add("Java");
                                        strList.add("Python");
                                        strList.add("Php");

                                        Stream<String> strStream = strList.stream();

                                        Stream<String> jFilter = strStream.filter(str -> {
                                        System.out.println("Filtering" + str);
                                        return str.startsWith("J");
                                        });

                                        System.out.println("After Stream creation");
                                        strList.add("JavaScript"); // element added after filter creation
                                        strList.add("JQuery"); // element added after filter creation

                                        System.out.println(Arrays.toString(jFilter.toArray()));

                                        }


                                        Output:



                                        After Stream creation
                                        FilteringJava
                                        FilteringPython
                                        FilteringPhp
                                        FilteringJavaScript
                                        FilteringJQuery
                                        [Java, JavaScript, JQuery]





                                        share|improve this answer












                                        Its because the stream never got evaluated. you never called a "Terminal operation" on that stream for it to get executed as they're lazy.



                                        Look at a modification of your code and the output. The filtering actually takes place when you call the Terminal Operator.



                                         public static void main(String args){
                                        List<String> strList = new ArrayList<>();
                                        strList.add("Java");
                                        strList.add("Python");
                                        strList.add("Php");

                                        Stream<String> strStream = strList.stream();

                                        Stream<String> jFilter = strStream.filter(str -> {
                                        System.out.println("Filtering" + str);
                                        return str.startsWith("J");
                                        });

                                        System.out.println("After Stream creation");
                                        strList.add("JavaScript"); // element added after filter creation
                                        strList.add("JQuery"); // element added after filter creation

                                        System.out.println(Arrays.toString(jFilter.toArray()));

                                        }


                                        Output:



                                        After Stream creation
                                        FilteringJava
                                        FilteringPython
                                        FilteringPhp
                                        FilteringJavaScript
                                        FilteringJQuery
                                        [Java, JavaScript, JQuery]






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered 10 hours ago









                                        Bandi Kishore

                                        3,3341730




                                        3,3341730























                                            1














                                            As explained in the official documentation at ,https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html, streams have no storage, and so are more like iterators than collections, and are evaluated lazily.



                                            So, nothing really happens with respect to the stream until you invoke the terminal operation toArray()






                                            share|improve this answer


























                                              1














                                              As explained in the official documentation at ,https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html, streams have no storage, and so are more like iterators than collections, and are evaluated lazily.



                                              So, nothing really happens with respect to the stream until you invoke the terminal operation toArray()






                                              share|improve this answer
























                                                1












                                                1








                                                1






                                                As explained in the official documentation at ,https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html, streams have no storage, and so are more like iterators than collections, and are evaluated lazily.



                                                So, nothing really happens with respect to the stream until you invoke the terminal operation toArray()






                                                share|improve this answer












                                                As explained in the official documentation at ,https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html, streams have no storage, and so are more like iterators than collections, and are evaluated lazily.



                                                So, nothing really happens with respect to the stream until you invoke the terminal operation toArray()







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered 10 hours ago









                                                GreyBeardedGeek

                                                20.5k12845




                                                20.5k12845























                                                    1














                                                    @Hadi J's comment but it should be answer according to the rules.




                                                    Because streams are lazy and when you call terminal operation it executed.







                                                    share|improve this answer


























                                                      1














                                                      @Hadi J's comment but it should be answer according to the rules.




                                                      Because streams are lazy and when you call terminal operation it executed.







                                                      share|improve this answer
























                                                        1












                                                        1








                                                        1






                                                        @Hadi J's comment but it should be answer according to the rules.




                                                        Because streams are lazy and when you call terminal operation it executed.







                                                        share|improve this answer












                                                        @Hadi J's comment but it should be answer according to the rules.




                                                        Because streams are lazy and when you call terminal operation it executed.








                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered 10 hours ago









                                                        user5377037

                                                        7,212122456




                                                        7,212122456






























                                                            draft saved

                                                            draft discarded




















































                                                            Thanks for contributing an answer to Stack Overflow!


                                                            • Please be sure to answer the question. Provide details and share your research!

                                                            But avoid



                                                            • Asking for help, clarification, or responding to other answers.

                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                            To learn more, see our tips on writing great answers.





                                                            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                            Please pay close attention to the following guidance:


                                                            • Please be sure to answer the question. Provide details and share your research!

                                                            But avoid



                                                            • Asking for help, clarification, or responding to other answers.

                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                            To learn more, see our tips on writing great answers.




                                                            draft saved


                                                            draft discarded














                                                            StackExchange.ready(
                                                            function () {
                                                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53896175%2fconsidering-list-elements-that-are-added-after-filtered-stream-creation%23new-answer', 'question_page');
                                                            }
                                                            );

                                                            Post as a guest















                                                            Required, but never shown





















































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown

































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown







                                                            Popular posts from this blog

                                                            Contact image not getting when fetch all contact list from iPhone by CNContact

                                                            count number of partitions of a set with n elements into k subsets

                                                            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks