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());