qdrien
qdrien

Reputation: 143

Joining "parallel" lists in a stream using collect()

I'm having trouble with joining lists created in a "parallelStream()". Here is the situation :

What I'd like to do (and I expected it to work, following the last bullet point of this answer) is the following :

List<Edge> edges = pairs.parallelStream()
        .map(p -> align(p.first(), p.second()))
        .collect(ArrayList::new, List::add, List::addAll);

With align() doing CPU-intensive work (which is why I need to "parallelize" it in the first place) and returning a List<Edge>.

The use of collect() prevents me from compiling, giving the following error :

Error: java: incompatible types: cannot infer type-variable(s) R,E (argument mismatch; invalid method reference incompatible types: ArrayList< Edge > cannot be converted to int)

Note that I did manage to make similar (but "uglier" imo) versions work, which confuses me even more:

v1 :

List<List<Edge>> collect = pairs.parallelStream()
        .map(p -> align(p.first(), p.second()))
        .collect(Collectors.toList());
collect.forEach(l -> l.forEach(edges::add));

v2 :

List<Edge> edges = new ArrayList<>();
pairs.parallelStream()
        .map(p -> align(p.first(), p.second()))
        .collect(Collectors.toList()).forEach(edges::addAll);

Can someone help me with this? I would like to avoid giving up and using "v2" ;)

Upvotes: 4

Views: 3024

Answers (2)

Misha
Misha

Reputation: 28133

You can also fix this by replacing List::add with List::addAll as the second argument to collect:

List<Edge> edges = pairs.parallelStream()
        .map(p -> align(p.first(), p.second()))
        .collect(ArrayList::new, List::addAll, List::addAll);

Upvotes: 3

Louis Wasserman
Louis Wasserman

Reputation: 198023

It's not 100% clear, but it looks like you probably want

List<Edge> edges = pairs.parallelStream()
    .flatMap(p -> align(p.first(), p.second()).stream())
    .collect(Collectors.toList());

Upvotes: 5

Related Questions