How does the reduce() method work in Java 8?In Stream reduce method, must the identity always be 0 for sum and 1 for multiplication?Is Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?How does the Java 'for each' loop work?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?How do I convert a String to an int in Java?Creating a memory leak with JavaJava 8 List<V> into Map<K, V>

Acronyms in HDD specification

Why are solar panels kept tilted?

Offered a new position but unknown about salary?

Why does SSL Labs now consider CBC suites weak?

Is it wrong to omit object pronouns in these sentences?

"The van's really booking"

Is there any good reason to write "it is easy to see"?

How to continually let my readers know what time it is in my story, in an organic way?

Is this possible when it comes to the relations of P, NP, NP-Hard and NP-Complete?

Wireless headphones interfere with Wi-Fi signal on laptop

Why are BJTs common in output stages of power amplifiers?

How do I adjust encounters to challenge my lycanthrope players without negating their cool new abilities?

Is there any way to adjust the damage type of the Eldritch Blast cantrip so that it does fire damage?

Were any toxic metals used in the International Space Station?

Should generated documentation be stored in a Git repository?

Why is it harder to turn a motor/generator with shorted terminals?

How can a layman easily get the consensus view of what academia *thinks* about a subject?

Substring join or additional table, which is faster?

Biology of a Firestarter

Why can't I share a one use code with anyone else?

Is there an academic word that means "to split hairs over"?

Why did the soldiers of the North disobey Jon?

Can my Serbian girlfriend apply for a UK Standard Visitor visa and stay for the whole 6 months?

Was the dragon prowess intentionally downplayed in S08E04?



How does the reduce() method work in Java 8?


In Stream reduce method, must the identity always be 0 for sum and 1 for multiplication?Is Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?How does the Java 'for each' loop work?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?How do I convert a String to an int in Java?Creating a memory leak with JavaJava 8 List<V> into Map<K, V>






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








17















I try to understand how does the reduce() method work in java-8.



For example I have this code:



public class App 

public static void main(String[] args)
String[] arr = "lorem", "ipsum", "sit", "amet";
List<String> strs = Arrays.asList(arr);

int ijk = strs.stream().reduce(0,
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);
System.out.println(ijk);




And the output is this:



Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = ipsum
Accumulator, a = 10, b = sit
Accumulator, a = 13, b = amet
17


It is a sum of the length of these strings. And I see that the combiner is not accessed, so it will not multiply the numbers, it only adds the numbers.



But if I have these stream:



int ijk = strs.parallelStream().reduce(0, 
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);

System.out.println(ijk);


This is the output:



Accumulator, a = 0, b = ipsum
Accumulator, a = 0, b = lorem
Accumulator, a = 0, b = sit
Combiner
Accumulator, a = 0, b = amet
Combiner
Combiner
300


I see that the Accumulator and Combiner are accessed both, but only the multiplication is return. So what's happen with the sum?










share|improve this question



















  • 6





    combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

    – Eugene
    May 3 at 12:50


















17















I try to understand how does the reduce() method work in java-8.



For example I have this code:



public class App 

public static void main(String[] args)
String[] arr = "lorem", "ipsum", "sit", "amet";
List<String> strs = Arrays.asList(arr);

int ijk = strs.stream().reduce(0,
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);
System.out.println(ijk);




And the output is this:



Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = ipsum
Accumulator, a = 10, b = sit
Accumulator, a = 13, b = amet
17


It is a sum of the length of these strings. And I see that the combiner is not accessed, so it will not multiply the numbers, it only adds the numbers.



But if I have these stream:



int ijk = strs.parallelStream().reduce(0, 
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);

System.out.println(ijk);


This is the output:



Accumulator, a = 0, b = ipsum
Accumulator, a = 0, b = lorem
Accumulator, a = 0, b = sit
Combiner
Accumulator, a = 0, b = amet
Combiner
Combiner
300


I see that the Accumulator and Combiner are accessed both, but only the multiplication is return. So what's happen with the sum?










share|improve this question



















  • 6





    combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

    – Eugene
    May 3 at 12:50














17












17








17


5






I try to understand how does the reduce() method work in java-8.



For example I have this code:



public class App 

public static void main(String[] args)
String[] arr = "lorem", "ipsum", "sit", "amet";
List<String> strs = Arrays.asList(arr);

int ijk = strs.stream().reduce(0,
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);
System.out.println(ijk);




And the output is this:



Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = ipsum
Accumulator, a = 10, b = sit
Accumulator, a = 13, b = amet
17


It is a sum of the length of these strings. And I see that the combiner is not accessed, so it will not multiply the numbers, it only adds the numbers.



But if I have these stream:



int ijk = strs.parallelStream().reduce(0, 
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);

System.out.println(ijk);


This is the output:



Accumulator, a = 0, b = ipsum
Accumulator, a = 0, b = lorem
Accumulator, a = 0, b = sit
Combiner
Accumulator, a = 0, b = amet
Combiner
Combiner
300


I see that the Accumulator and Combiner are accessed both, but only the multiplication is return. So what's happen with the sum?










share|improve this question
















I try to understand how does the reduce() method work in java-8.



For example I have this code:



public class App 

public static void main(String[] args)
String[] arr = "lorem", "ipsum", "sit", "amet";
List<String> strs = Arrays.asList(arr);

int ijk = strs.stream().reduce(0,
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);
System.out.println(ijk);




And the output is this:



Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = ipsum
Accumulator, a = 10, b = sit
Accumulator, a = 13, b = amet
17


It is a sum of the length of these strings. And I see that the combiner is not accessed, so it will not multiply the numbers, it only adds the numbers.



But if I have these stream:



int ijk = strs.parallelStream().reduce(0, 
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a * b;
);

System.out.println(ijk);


This is the output:



Accumulator, a = 0, b = ipsum
Accumulator, a = 0, b = lorem
Accumulator, a = 0, b = sit
Combiner
Accumulator, a = 0, b = amet
Combiner
Combiner
300


I see that the Accumulator and Combiner are accessed both, but only the multiplication is return. So what's happen with the sum?







java java-8 java-stream reduce






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 3 at 13:30









Nikolas

14.9k53871




14.9k53871










asked May 3 at 12:47









gabygaby

701214




701214







  • 6





    combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

    – Eugene
    May 3 at 12:50













  • 6





    combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

    – Eugene
    May 3 at 12:50








6




6





combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

– Eugene
May 3 at 12:50






combiner is only called for a parallel stream. also read the documentation of reduce carefully, you can not do summation in accumulator and multiplication in combiner and expect something meaningful as a result

– Eugene
May 3 at 12:50













4 Answers
4






active

oldest

votes


















16














You should read the documentation of reduce that says:




Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:



combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)




In your case, you are breaking that law (doing a sum in accumulator and multiplication in the combiner), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).



Besides, the combiner is only called for a parallel stream.



Of course, your entire approach could be simplified to:



Arrays.asList("lorem", "ipsum", "sit", "amet")
.stream()
.mapToInt(String::length)
.sum();


If you are doing that just for learning purposes, a correct reduce would be (to get the sum):



strs.parallelStream()
.reduce(0,
(a, b) ->
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
,
(a, b) ->
System.out.println("Combiner");
return a + b;
);





share|improve this answer
































    8














    The Key Concepts: Identity, Accumulator, and Combiner



    Stream.reduce() operation : let’s break down the operation’s participant elements into separate blocks. That way, we’ll understand more easily the role that each one plays




    • Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty


    • itemAccumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream


    • Combiner – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream
      Combiner – a function used to combine the partial result of the reduction operation when the reduction is parallelized, or when there’s a mismatch between the types of the accumulator arguments and the types of the accumulator implementation


    When a stream executes in parallel, the Java runtime splits the stream into multiple substreams. In such cases, we need to use a function to combine the results of the substreams into a single one. This is the role of the combiner




    Case 1 : Combiner works with parallelStream as showed in your example



    Case 2 : Example accumulator with different type of arguments



    In this case, we have a stream of User objects, and the types of the accumulator arguments are Integer and User. However, the accumulator implementation is a sum of Integers, so the compiler just can’t infer the type of the user parameter.



    List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge());


    Compile Error



    The method reduce(User, BinaryOperator<User>) in the type Stream<User> is not applicable for the arguments (int, (<no type> partialAgeResult, <no type> user) -> )


    We can fix this issue by using a combiner: which is method reference Integer::sum or by using lambda expression (a,b)->a+b



    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(),Integer::sum);


    To put it simply, if we use sequential streams and the types of the accumulator arguments and the types of its implementation match, we don’t need to use a combiner.






    share|improve this answer
































      8














      There are 3 ways to reduce using java-stream. In a nutshell, Stream::reduce starts with two consequent items (or an identity value one with the first one) and performs an operation with them producing new reduced value. For each next item, the same happens and an operation is performed with the reduced value.



      Let's say you have a stream of 'a', 'b', 'c' and 'd'. The reduction performs the following sequence of operations:




      1. result = operationOn('a', 'b') - the operationOn might be anything (sum of the lengths of inputs..)

      2. result = operationOn(result, 'c')

      3. result = operationOn(result, 'd')

      4. result is returned

      The methods are:



      • Optional<T> reduce(BinaryOperator<T> accumulator) performs a reduction on the elements. Starts with the first two items producing a reduced value, then each item with the reduced value. The Optional<T> is returned since it is not guaranteed the input stream is not empty.


      • T reduce(T identity, BinaryOperator<T> accumulator) does the same as the method above, except the identity value is given as the first item. The T is returned since there is always at least one item guaranteed, because of T identity.


      • U reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) does the same as the method above, with an addition that the functions are combined. The U is returned since there is always at least one item guaranteed, because of U identity.






      share|improve this answer

























      • Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

        – Holger
        May 6 at 10:46











      • "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

        – Nikolas
        May 6 at 10:48











      • Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

        – Holger
        May 6 at 10:51


















      1














      I assume you chose to do addition and multiplication just as a demo to see what exactly happens.



      As you already noticed, and as was already mentioned, the combiner is only called on parallel streams.



      In short, on parallel strams, a part of the stream (resp. the underlying Spliterator) is cut off and processed by a different thread. After several parts are processed, their result is combined with a combiner.



      In your case, the four elements all are processed by a different thread, and combination happens element-wise then. That's why you don't see any addition (apart from 0 +) being applied, but only multiplication.



      In order to get a meaningful result, however, you should switch from * to + and instead do a more meaningful output.






      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%2f55970149%2fhow-does-the-reduce-method-work-in-java-8%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        16














        You should read the documentation of reduce that says:




        Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:



        combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)




        In your case, you are breaking that law (doing a sum in accumulator and multiplication in the combiner), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).



        Besides, the combiner is only called for a parallel stream.



        Of course, your entire approach could be simplified to:



        Arrays.asList("lorem", "ipsum", "sit", "amet")
        .stream()
        .mapToInt(String::length)
        .sum();


        If you are doing that just for learning purposes, a correct reduce would be (to get the sum):



        strs.parallelStream()
        .reduce(0,
        (a, b) ->
        System.out.println("Accumulator, a = " + a + ", b = " + b);
        return a + b.length();
        ,
        (a, b) ->
        System.out.println("Combiner");
        return a + b;
        );





        share|improve this answer





























          16














          You should read the documentation of reduce that says:




          Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:



          combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)




          In your case, you are breaking that law (doing a sum in accumulator and multiplication in the combiner), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).



          Besides, the combiner is only called for a parallel stream.



          Of course, your entire approach could be simplified to:



          Arrays.asList("lorem", "ipsum", "sit", "amet")
          .stream()
          .mapToInt(String::length)
          .sum();


          If you are doing that just for learning purposes, a correct reduce would be (to get the sum):



          strs.parallelStream()
          .reduce(0,
          (a, b) ->
          System.out.println("Accumulator, a = " + a + ", b = " + b);
          return a + b.length();
          ,
          (a, b) ->
          System.out.println("Combiner");
          return a + b;
          );





          share|improve this answer



























            16












            16








            16







            You should read the documentation of reduce that says:




            Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:



            combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)




            In your case, you are breaking that law (doing a sum in accumulator and multiplication in the combiner), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).



            Besides, the combiner is only called for a parallel stream.



            Of course, your entire approach could be simplified to:



            Arrays.asList("lorem", "ipsum", "sit", "amet")
            .stream()
            .mapToInt(String::length)
            .sum();


            If you are doing that just for learning purposes, a correct reduce would be (to get the sum):



            strs.parallelStream()
            .reduce(0,
            (a, b) ->
            System.out.println("Accumulator, a = " + a + ", b = " + b);
            return a + b.length();
            ,
            (a, b) ->
            System.out.println("Combiner");
            return a + b;
            );





            share|improve this answer















            You should read the documentation of reduce that says:




            Additionally, the combiner function must be compatible with the accumulator function; for all u and t, the following must hold:



            combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)




            In your case, you are breaking that law (doing a sum in accumulator and multiplication in the combiner), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).



            Besides, the combiner is only called for a parallel stream.



            Of course, your entire approach could be simplified to:



            Arrays.asList("lorem", "ipsum", "sit", "amet")
            .stream()
            .mapToInt(String::length)
            .sum();


            If you are doing that just for learning purposes, a correct reduce would be (to get the sum):



            strs.parallelStream()
            .reduce(0,
            (a, b) ->
            System.out.println("Accumulator, a = " + a + ", b = " + b);
            return a + b.length();
            ,
            (a, b) ->
            System.out.println("Combiner");
            return a + b;
            );






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 3 at 13:12









            John Kugelman

            251k55411463




            251k55411463










            answered May 3 at 12:57









            EugeneEugene

            73.7k9104179




            73.7k9104179























                8














                The Key Concepts: Identity, Accumulator, and Combiner



                Stream.reduce() operation : let’s break down the operation’s participant elements into separate blocks. That way, we’ll understand more easily the role that each one plays




                • Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty


                • itemAccumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream


                • Combiner – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream
                  Combiner – a function used to combine the partial result of the reduction operation when the reduction is parallelized, or when there’s a mismatch between the types of the accumulator arguments and the types of the accumulator implementation


                When a stream executes in parallel, the Java runtime splits the stream into multiple substreams. In such cases, we need to use a function to combine the results of the substreams into a single one. This is the role of the combiner




                Case 1 : Combiner works with parallelStream as showed in your example



                Case 2 : Example accumulator with different type of arguments



                In this case, we have a stream of User objects, and the types of the accumulator arguments are Integer and User. However, the accumulator implementation is a sum of Integers, so the compiler just can’t infer the type of the user parameter.



                List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
                int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge());


                Compile Error



                The method reduce(User, BinaryOperator<User>) in the type Stream<User> is not applicable for the arguments (int, (<no type> partialAgeResult, <no type> user) -> )


                We can fix this issue by using a combiner: which is method reference Integer::sum or by using lambda expression (a,b)->a+b



                int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(),Integer::sum);


                To put it simply, if we use sequential streams and the types of the accumulator arguments and the types of its implementation match, we don’t need to use a combiner.






                share|improve this answer





























                  8














                  The Key Concepts: Identity, Accumulator, and Combiner



                  Stream.reduce() operation : let’s break down the operation’s participant elements into separate blocks. That way, we’ll understand more easily the role that each one plays




                  • Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty


                  • itemAccumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream


                  • Combiner – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream
                    Combiner – a function used to combine the partial result of the reduction operation when the reduction is parallelized, or when there’s a mismatch between the types of the accumulator arguments and the types of the accumulator implementation


                  When a stream executes in parallel, the Java runtime splits the stream into multiple substreams. In such cases, we need to use a function to combine the results of the substreams into a single one. This is the role of the combiner




                  Case 1 : Combiner works with parallelStream as showed in your example



                  Case 2 : Example accumulator with different type of arguments



                  In this case, we have a stream of User objects, and the types of the accumulator arguments are Integer and User. However, the accumulator implementation is a sum of Integers, so the compiler just can’t infer the type of the user parameter.



                  List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
                  int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge());


                  Compile Error



                  The method reduce(User, BinaryOperator<User>) in the type Stream<User> is not applicable for the arguments (int, (<no type> partialAgeResult, <no type> user) -> )


                  We can fix this issue by using a combiner: which is method reference Integer::sum or by using lambda expression (a,b)->a+b



                  int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(),Integer::sum);


                  To put it simply, if we use sequential streams and the types of the accumulator arguments and the types of its implementation match, we don’t need to use a combiner.






                  share|improve this answer



























                    8












                    8








                    8







                    The Key Concepts: Identity, Accumulator, and Combiner



                    Stream.reduce() operation : let’s break down the operation’s participant elements into separate blocks. That way, we’ll understand more easily the role that each one plays




                    • Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty


                    • itemAccumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream


                    • Combiner – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream
                      Combiner – a function used to combine the partial result of the reduction operation when the reduction is parallelized, or when there’s a mismatch between the types of the accumulator arguments and the types of the accumulator implementation


                    When a stream executes in parallel, the Java runtime splits the stream into multiple substreams. In such cases, we need to use a function to combine the results of the substreams into a single one. This is the role of the combiner




                    Case 1 : Combiner works with parallelStream as showed in your example



                    Case 2 : Example accumulator with different type of arguments



                    In this case, we have a stream of User objects, and the types of the accumulator arguments are Integer and User. However, the accumulator implementation is a sum of Integers, so the compiler just can’t infer the type of the user parameter.



                    List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
                    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge());


                    Compile Error



                    The method reduce(User, BinaryOperator<User>) in the type Stream<User> is not applicable for the arguments (int, (<no type> partialAgeResult, <no type> user) -> )


                    We can fix this issue by using a combiner: which is method reference Integer::sum or by using lambda expression (a,b)->a+b



                    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(),Integer::sum);


                    To put it simply, if we use sequential streams and the types of the accumulator arguments and the types of its implementation match, we don’t need to use a combiner.






                    share|improve this answer















                    The Key Concepts: Identity, Accumulator, and Combiner



                    Stream.reduce() operation : let’s break down the operation’s participant elements into separate blocks. That way, we’ll understand more easily the role that each one plays




                    • Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty


                    • itemAccumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream


                    • Combiner – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream
                      Combiner – a function used to combine the partial result of the reduction operation when the reduction is parallelized, or when there’s a mismatch between the types of the accumulator arguments and the types of the accumulator implementation


                    When a stream executes in parallel, the Java runtime splits the stream into multiple substreams. In such cases, we need to use a function to combine the results of the substreams into a single one. This is the role of the combiner




                    Case 1 : Combiner works with parallelStream as showed in your example



                    Case 2 : Example accumulator with different type of arguments



                    In this case, we have a stream of User objects, and the types of the accumulator arguments are Integer and User. However, the accumulator implementation is a sum of Integers, so the compiler just can’t infer the type of the user parameter.



                    List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
                    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge());


                    Compile Error



                    The method reduce(User, BinaryOperator<User>) in the type Stream<User> is not applicable for the arguments (int, (<no type> partialAgeResult, <no type> user) -> )


                    We can fix this issue by using a combiner: which is method reference Integer::sum or by using lambda expression (a,b)->a+b



                    int computedAges = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(),Integer::sum);


                    To put it simply, if we use sequential streams and the types of the accumulator arguments and the types of its implementation match, we don’t need to use a combiner.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 3 at 15:12

























                    answered May 3 at 13:00









                    DeadpoolDeadpool

                    9,0022831




                    9,0022831





















                        8














                        There are 3 ways to reduce using java-stream. In a nutshell, Stream::reduce starts with two consequent items (or an identity value one with the first one) and performs an operation with them producing new reduced value. For each next item, the same happens and an operation is performed with the reduced value.



                        Let's say you have a stream of 'a', 'b', 'c' and 'd'. The reduction performs the following sequence of operations:




                        1. result = operationOn('a', 'b') - the operationOn might be anything (sum of the lengths of inputs..)

                        2. result = operationOn(result, 'c')

                        3. result = operationOn(result, 'd')

                        4. result is returned

                        The methods are:



                        • Optional<T> reduce(BinaryOperator<T> accumulator) performs a reduction on the elements. Starts with the first two items producing a reduced value, then each item with the reduced value. The Optional<T> is returned since it is not guaranteed the input stream is not empty.


                        • T reduce(T identity, BinaryOperator<T> accumulator) does the same as the method above, except the identity value is given as the first item. The T is returned since there is always at least one item guaranteed, because of T identity.


                        • U reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) does the same as the method above, with an addition that the functions are combined. The U is returned since there is always at least one item guaranteed, because of U identity.






                        share|improve this answer

























                        • Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                          – Holger
                          May 6 at 10:46











                        • "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                          – Nikolas
                          May 6 at 10:48











                        • Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                          – Holger
                          May 6 at 10:51















                        8














                        There are 3 ways to reduce using java-stream. In a nutshell, Stream::reduce starts with two consequent items (or an identity value one with the first one) and performs an operation with them producing new reduced value. For each next item, the same happens and an operation is performed with the reduced value.



                        Let's say you have a stream of 'a', 'b', 'c' and 'd'. The reduction performs the following sequence of operations:




                        1. result = operationOn('a', 'b') - the operationOn might be anything (sum of the lengths of inputs..)

                        2. result = operationOn(result, 'c')

                        3. result = operationOn(result, 'd')

                        4. result is returned

                        The methods are:



                        • Optional<T> reduce(BinaryOperator<T> accumulator) performs a reduction on the elements. Starts with the first two items producing a reduced value, then each item with the reduced value. The Optional<T> is returned since it is not guaranteed the input stream is not empty.


                        • T reduce(T identity, BinaryOperator<T> accumulator) does the same as the method above, except the identity value is given as the first item. The T is returned since there is always at least one item guaranteed, because of T identity.


                        • U reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) does the same as the method above, with an addition that the functions are combined. The U is returned since there is always at least one item guaranteed, because of U identity.






                        share|improve this answer

























                        • Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                          – Holger
                          May 6 at 10:46











                        • "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                          – Nikolas
                          May 6 at 10:48











                        • Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                          – Holger
                          May 6 at 10:51













                        8












                        8








                        8







                        There are 3 ways to reduce using java-stream. In a nutshell, Stream::reduce starts with two consequent items (or an identity value one with the first one) and performs an operation with them producing new reduced value. For each next item, the same happens and an operation is performed with the reduced value.



                        Let's say you have a stream of 'a', 'b', 'c' and 'd'. The reduction performs the following sequence of operations:




                        1. result = operationOn('a', 'b') - the operationOn might be anything (sum of the lengths of inputs..)

                        2. result = operationOn(result, 'c')

                        3. result = operationOn(result, 'd')

                        4. result is returned

                        The methods are:



                        • Optional<T> reduce(BinaryOperator<T> accumulator) performs a reduction on the elements. Starts with the first two items producing a reduced value, then each item with the reduced value. The Optional<T> is returned since it is not guaranteed the input stream is not empty.


                        • T reduce(T identity, BinaryOperator<T> accumulator) does the same as the method above, except the identity value is given as the first item. The T is returned since there is always at least one item guaranteed, because of T identity.


                        • U reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) does the same as the method above, with an addition that the functions are combined. The U is returned since there is always at least one item guaranteed, because of U identity.






                        share|improve this answer















                        There are 3 ways to reduce using java-stream. In a nutshell, Stream::reduce starts with two consequent items (or an identity value one with the first one) and performs an operation with them producing new reduced value. For each next item, the same happens and an operation is performed with the reduced value.



                        Let's say you have a stream of 'a', 'b', 'c' and 'd'. The reduction performs the following sequence of operations:




                        1. result = operationOn('a', 'b') - the operationOn might be anything (sum of the lengths of inputs..)

                        2. result = operationOn(result, 'c')

                        3. result = operationOn(result, 'd')

                        4. result is returned

                        The methods are:



                        • Optional<T> reduce(BinaryOperator<T> accumulator) performs a reduction on the elements. Starts with the first two items producing a reduced value, then each item with the reduced value. The Optional<T> is returned since it is not guaranteed the input stream is not empty.


                        • T reduce(T identity, BinaryOperator<T> accumulator) does the same as the method above, except the identity value is given as the first item. The T is returned since there is always at least one item guaranteed, because of T identity.


                        • U reduce(U identity, BiFunction<U,? super T, U> accumulator, BinaryOperator<U> combiner) does the same as the method above, with an addition that the functions are combined. The U is returned since there is always at least one item guaranteed, because of U identity.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited May 6 at 10:54

























                        answered May 3 at 13:08









                        NikolasNikolas

                        14.9k53871




                        14.9k53871












                        • Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                          – Holger
                          May 6 at 10:46











                        • "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                          – Nikolas
                          May 6 at 10:48











                        • Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                          – Holger
                          May 6 at 10:51

















                        • Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                          – Holger
                          May 6 at 10:46











                        • "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                          – Nikolas
                          May 6 at 10:48











                        • Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                          – Holger
                          May 6 at 10:51
















                        Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                        – Holger
                        May 6 at 10:46





                        Calling the identity value a “default value” is misleading, if not worse. If you want a default value, use reduce(function).orElse(default). Further, the explanation for the 3rd overload, “with an addition that the functions are combined” is not really helpful. The point of the third version is, that it allows to reduce to a different result type than the Stream’s element type. The difference to the straight-forward alternative, stream.map(…).reduce(id, function) is that you can use an optimized function for combining a source element (T) with a result element (U), if there as one.

                        – Holger
                        May 6 at 10:46













                        "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                        – Nikolas
                        May 6 at 10:48





                        "initial" might be better than "default" right? I still improve my English. Thanks for a note :)

                        – Nikolas
                        May 6 at 10:48













                        Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                        – Holger
                        May 6 at 10:51





                        Well, the term “identity value” is already a term on its own, which has no better replacement. Neither “initial” nor “default” will be sufficient. The contract of an identity value is explained right in the documentation, but, as explained in this answer, it’s a term, not just invented for the reduction operation.

                        – Holger
                        May 6 at 10:51











                        1














                        I assume you chose to do addition and multiplication just as a demo to see what exactly happens.



                        As you already noticed, and as was already mentioned, the combiner is only called on parallel streams.



                        In short, on parallel strams, a part of the stream (resp. the underlying Spliterator) is cut off and processed by a different thread. After several parts are processed, their result is combined with a combiner.



                        In your case, the four elements all are processed by a different thread, and combination happens element-wise then. That's why you don't see any addition (apart from 0 +) being applied, but only multiplication.



                        In order to get a meaningful result, however, you should switch from * to + and instead do a more meaningful output.






                        share|improve this answer



























                          1














                          I assume you chose to do addition and multiplication just as a demo to see what exactly happens.



                          As you already noticed, and as was already mentioned, the combiner is only called on parallel streams.



                          In short, on parallel strams, a part of the stream (resp. the underlying Spliterator) is cut off and processed by a different thread. After several parts are processed, their result is combined with a combiner.



                          In your case, the four elements all are processed by a different thread, and combination happens element-wise then. That's why you don't see any addition (apart from 0 +) being applied, but only multiplication.



                          In order to get a meaningful result, however, you should switch from * to + and instead do a more meaningful output.






                          share|improve this answer

























                            1












                            1








                            1







                            I assume you chose to do addition and multiplication just as a demo to see what exactly happens.



                            As you already noticed, and as was already mentioned, the combiner is only called on parallel streams.



                            In short, on parallel strams, a part of the stream (resp. the underlying Spliterator) is cut off and processed by a different thread. After several parts are processed, their result is combined with a combiner.



                            In your case, the four elements all are processed by a different thread, and combination happens element-wise then. That's why you don't see any addition (apart from 0 +) being applied, but only multiplication.



                            In order to get a meaningful result, however, you should switch from * to + and instead do a more meaningful output.






                            share|improve this answer













                            I assume you chose to do addition and multiplication just as a demo to see what exactly happens.



                            As you already noticed, and as was already mentioned, the combiner is only called on parallel streams.



                            In short, on parallel strams, a part of the stream (resp. the underlying Spliterator) is cut off and processed by a different thread. After several parts are processed, their result is combined with a combiner.



                            In your case, the four elements all are processed by a different thread, and combination happens element-wise then. That's why you don't see any addition (apart from 0 +) being applied, but only multiplication.



                            In order to get a meaningful result, however, you should switch from * to + and instead do a more meaningful output.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered May 3 at 12:56









                            glglglglglgl

                            68.7k796169




                            68.7k796169



























                                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.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55970149%2fhow-does-the-reduce-method-work-in-java-8%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

                                Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

                                Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

                                Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020