Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

java - How to reduce given list by using 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 by using .filter() method. But, is there any possibility to achieve the same with .reduce() method. Hope, .reduce() method filtered out all the other elements by performing given BynaryOperation and return reduced list.

If my understanding is not correct on .reduce() method, please let me know what exactly this method do.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your understanding of reduction is wrong. reduce will apply a function on all elements repeatedly to get one single result.

You seem to think of reduce like doing

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

whereas, in fact, it does

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

Though, this is a conceptional view, the exact order of operations is unspecified. A sequential execution will be like (((1 op 2) op 3) op 4)… while a parallel execution will be a mixture of an execution like the tree above and partial sequential execution(s).


You can abuse reduce to create a result list if you first convert each element into a List and then use a list operation which concatenates each list, however, there are two problems with this:

  • It doesn’t provide the desired “skip each second element (of the original list)” logic; if you look at the tree above, it should become clear, that it is impossible to formulate a correct op function which does that in every possible execution scenario
  • creating temporary lists and concatenating them is very inefficient

The latter point can be solved by using collect, which is a mutable reduction, hence, allows you to use mutable lists to which you can add items, however, it does not address the first point, including the desired filter would violate the contract and only work in a sequential execution.

So the solution is to define a filter for all elements in the scope of the source list, followed by a mutable reduction to create the result list using collect, and, big surprise, that’s exactly what you original code does:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...