BiFunction – apply method should always return the second argument. Why?

I am trying to identify the numbers from a list whose predecessor is greater than its value.

In the lambda expression if I return b, it behaves as expected but if I return a, it gives wrong output.

What is the difference between these two return statements?

    List<Integer> list = Arrays.asList(1,2,3,4,5,8,7);
    List<Integer> result = new ArrayList<>();
    list.stream().reduce((a,b) -> {if (a < b) result.add(a);return b;});
    System.out.println(result);

    result.clear();
    list.stream().reduce((a,b) -> {if (a < b) result.add(a);return a;});
    System.out.println(result);

Output:

[1, 2, 3, 4, 5]

[1, 1, 1, 1, 1, 1]

2
Leave a Reply

avatar
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

The reduction you are performing – using Optional<T> java.util.stream.Stream.reduce(BinaryOperator<T> accumulator) – is equivalent to the following pseudo code (taken from the Javadoc): boolean foundAny = false; T result = null; for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else { result = accumulator.apply(result, element); } } return foundAny ? Optional.of(result) : Optional.empty(); As you can see, the intermediate result of the reduction is passed as the first argument of the accumulator and the current element of the Stream is passed as the second argument. Hence, when your lambda expression returns the… Read more »

Jason
Guest

This is not a direct answer to your question, but since I said a stateful filter would be better, I felt oblige to show it. Take the follow stateful predicate: public class GreaterThanPreceding implements Predicate<Integer> { private Integer preceding = null; @Override public boolean test(Integer current) { boolean greaterThan = preceding == null || (current > preceding); preceding = current; return greaterThan; } } With that, the stream operation would look like this: List<Integer> collected = list.stream() .filter(new GreaterThanPreceding()) .collect(Collectors.toList()); System.out.println(collected);