How to reduce a given list using the Lambda expression.reduce () method

List<Integer> integers = Arrays.asList(1, 2, 3, 5, 6, 8, 9, 10); integers.stream().filter((integer) -> integer % 2 == 0).collect(Collectors.toList()); 

As shown above, integers is a list from which we need to filter only even numbers. I can achieve with the .filter() method. But is it possible to achieve the same .reduce() method. Hope .reduce() filtered out all the other elements by completing the BynaryOperation task and returning a shortened list.

If my understanding is incorrect in the .reduce() method, please let me know what exactly this method does.

+2
java lambda filter java-8 reduce
source share
2 answers

Your understanding of contraction is incorrect. reduce will reapply the function for all elements to get one result.

It seems you are thinking about cutting how to do

 1, 2, 3, 5, 6, 8, 9, 10 │ │ │ │ │ │ │ │ └op┘ └op┘ └op┘ └op┘ │ │ │ │ result list 

whereas, in fact, he

 1, 2, 3, 5, 6, 8, 9, 10 │ │ │ │ │ │ │ │ └op┘ └op┘ └op┘ └op┘ │ │ │ │ └─op─┘ └─op─┘ │ │ └────op────┘ │ final result value 

Although this is a conceptual representation, the exact order of operations is unspecified. Sequential execution will look like (((1 op 2) op 3) op 4)… , while parallel execution will be a mixture of execution, such as the tree above and partial sequential execution.


You can use reduce to create a list of results if you first convert each item to a List , and then use a list operation that combines each list, however there are two problems with this:

  • It does not provide the desired “skip every second element (from the source list)” logic; if you look at the tree above, it should become clear that it is not possible to formulate the correct op function that does this in all possible execution scenarios
  • creating temporary lists and concatenating them is very inefficient.

The last point can be resolved using collect , which is a mutable reduction, therefore, it allows the use of modified lists to which you can add items, but it does not apply to the first point, including the desired filter will violate the contract and will only work in sequential execution.

So, the solution is to define a filter for all the elements in the source list area, followed by a mutable shortcut to create a list of results using collect , and, to my great surprise, this is exactly what you original code does:

 … .filter(integer -> integer % 2 == 0).collect(Collectors.toList()); 
+10
source share

You can use the Stream.reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) method Stream.reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) , which takes three parameters:

  • identity: The identity element is both the initial abbreviation and the default result if there are no elements in the stream. In your case, it will be an empty list .
  • Battery: The battery function accepts two parameters: a partial recovery result and the next stream element (in this example, an integer). It applies validation for modulo 2 and then returns a new partial result. Compiler
  • : The goal is to combine internal temporary flow collectors-accumulators of flows that are parallel processes.

For example:

 BinaryOperator<ArrayList<Integer>> combiner = (x, y) -> { x.addAll(y); return x; }; BiFunction<ArrayList<Integer>, Integer, ArrayList<Integer>> accumulator = (x, y) -> { if (y % 2 == 0) { x.add(y); } return x; }; List<Integer> list = Stream.of(1, 2, 3, 5, 6, 8, 9, 10).reduce(new ArrayList<Integer>(), accumulator, combiner); System.out.println(list); 

Please note that this solution may not work for parallel threads. It's also too easy to stick with the .filter() approach, so I highly recommend you do this.

+7
source share

All Articles