Skip to main content

Reduce method in Stream Java 8 (Stream.reduce())

 Stream.reduce()

Before learning about the stream.reduce(), first we will learn two functional interfaces.

  • BinaryOperator<T>

    • Represents an operation upon two operands of the same type, producing a result of the same type as the operands.

    • This is a specialization of BiFunction for the case where the operands and the result are all of the same type.

    • The SAM is T apply(T t, T t);

  • BiFunction<T, U, R>

    • Represents a function that accepts two arguments and produces a result.

    • The SAM is R apply(T t, U u);

Now we will start the Stream.reduce()

  1. Reduction stream operations allow us to produce one single result from a sequence of elements.
  2. A reduction is a terminal operation that aggregates a stream into a type or a primitive. For example, a set of predefined reduction operations, such as average(), sum(), min(), max(), and count(), return one value by combining the elements of a stream.
  3. Stream.reduce() is a general-purpose method for generating our custom reduction operations.
  4. Before we look deeper into the Stream.reduce() operation, let's break down the operation's participant elements into separate blocks.
    1. Identity – an element that is the initial value of the reduction operation and the default result if the stream is empty.
    2. Accumulator – a function that takes two parameters: a partial result of the reduction operation and the next element of the stream.
    3. 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.
  5. The Stream.reduce() method is overloaded and present inside the Stream interface.
    1. Optional<T> reduce(BinaryOperator<T> accumulator);
      1. This method performs a reduction on the elements of this stream, using an associative accumulation function. It returns an Optional describing the reduced value if any.
    2. T reduce(T identity, BinaryOperator<T> accumulator);
      1. This method takes two parameters: the identity and the accumulator. It returns a new partial result. The Stream.reduce() method returns the result of the reduction.
    3. <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
      1. This method takes three parameters: the identity, the accumulator, and the combiner.
  6. Example for subpoints 1 and 2 of point 5:
    1. public class Test {

         public static void main(String[] args) {

             List<Book> books = new ArrayList<>();

             books.add(new Book("9781976704031", 9.99));

             books.add(new Book("9781976704032", 15.99));

             Book book = books.stream().reduce(new Book("9781976704033", 0.0), (b1, b2) -> {

                 b1.price = b1.price + b2.price;

                 return new Book(b1.isbn, b1.price);

             });

             //System.out.println(book);

             books.add(book);

             books.parallelStream().reduce((x, y) -> x.price > y.price ? x : y).ifPresent(System.out::println);

         }

      }


      class Book {

         String isbn;

         double price;

         Book(String isbn, double price) {

             this.isbn = isbn;

             this.price = price;

         }

         public String toString() {

             return "Book[" + isbn + ":" + price + "]";

         }

      }

  7. Example for subpoint 3 of point 5:
    1. int length = Arrays.asList("str1", "str2").parallelStream()

             .reduce(0, (accumulatedInt, str) -> accumulatedInt + str.length(),

                     (accumulatedInt1, accumulatedInt2) -> accumulatedInt1 + accumulatedInt2);

      System.out.println(length);
  8. In the above example if you are using a parallel stream then you don’t need to do the same thing in the accumulator and combiner. You can skip in the accumulator and do the same in the combiner. Below is an example of the same.
    1. int length1 = Arrays.asList("str1", "str2").parallelStream()

             .reduce(0, (accumulatedInt, str) -> str.length(),

                     (accumulatedInt1, accumulatedInt2) -> accumulatedInt1 + accumulatedInt2);

      System.out.println(length1);
  9. Why do we use the combiner function in the third version of the reduce method?
    1. To do parallel reduction to a different result type, we need two functions: one that accumulates T elements to intermediate U values and a second that combines the intermediate U values into a single U result.

Comments

Popular posts from this blog

How to add an existing project to a GitHub Repository

  Add Existing project to a GitHub Repository Step 1: Login into your GitHub account and create a new repository. Step 2: Go to your project folder on your machine and open git bash. After that runs the command “ git init ”. This command initialized the empty git repository on your local machine. Step 3: Create a file “. gitignore ” using the command “ echo > .gitignore ”. Add the file extension or file name inside this file, those you don’t want to commit to your repository. Git will ignore all those files that will be present inside this file. Step 4: Add all the files to the staging area using the command “git add .” This command adds all the files to the staging area and all these files are now ready for the commit. And with the help of the command “git status” , you can check that all the files are inside the staging area. Also, you can see the file extension or the file name mentioned inside the “.gitignore”  are ignored by git. Step 5: Commit the files that are pre...

Lambda Expression

What is Lambda Expression? In java 8, a powerful concept is added named Lambda Expression.  Lambda expression is an anonymous function (a nameless function that does not have a modifier, return type, and even the type of its arguments).  Lambda expression is that you can pass to a method whose argument type is functional interface i.e. an interface that is either annotated by @FunctionalInterface  annotation e.g. interfaces from java.util.function package, or an interface with a single abstract method e.g. Comparable, Comparator, Runnable, Callable, ActionListener, etc.  Lambda expression allows passing customized code to the java method that was not possible before java 8. Although before Java 8 the only option was to wrap your code as an object and pass it using anonymous inner class to the method. Lambda expression defines parameters and code that executed using those parameters. Let's take the simplest example of the lambda expression (String input) -> ...

How to install IntelliJ IDEA on Windows?

System Requirements and steps to install IntelliJ IDEA on Windows System Requirements:  Step 1: Download IntelliJ IDEA. Click here. Step 2: Run the downloaded exe file and click on next. Step 3: Check the checkboxes mentioned in the below image and click on next and then hit the install button. Step 4: Final step is to reboot your system before start using IntelliJ IDEA. Thank you, guys. Please do comment below if there is any query or feedback.