How to retainAll of List of Lists using stream red

2019-01-25 14:00发布

问题:

I faced following problem. I have a list of lists which i simply want to retainAll. I'm trying to do with streams

private List<List<Long>> ids = new ArrayList<List<Long>>();

// some ids.add(otherLists);  

List<Long> reduce = ids.stream().reduce(ids.get(0), (a, b) -> a.addAll(b));

unfortunately I got the error

Error:(72, 67) java: incompatible types: bad return type in lambda expression
    boolean cannot be converted to java.util.List<java.lang.Long> 

回答1:

addAll returns a boolean, not the union of the two lists. You want

List<Long> reduce = ids.stream().reduce(ids.get(0), (a, b) -> {
    a.addAll(b);
    return a;
});


回答2:

If you want to reduce (I think you mean flatten by that) the list of lists, you should do it like this:

import static java.util.stream.Collectors.toList

...

List<Long> reduce = ids.stream().flatMap(List::stream).collect(toList());

Using reduce, the first value should be the identity value which is not the case in your implementation, and your solution will produce unexpected results when running the stream in parallel (because addAll modifies the list in place, and in this case the identity value will be the same list for partial results).

You'd need to copy the content of the partial result list, and add the other list in it to make it working when the pipeline is run in parallel:

List<Long> reduce = ids.parallelStream().reduce(new ArrayList<>(), (a, b) -> {
    List<Long> list = new ArrayList<Long>(a);
    list.addAll(b);
    return list;
 });