Valid Supplier for collect method of stream

Viewed 740

I was just trying to create somewhat similar to Collectors.toList() of my own but it doesn't seem to work

import java.util.ArrayList;

public class ShipmentTracingDTO {

boolean destination = false;

public ShipmentTracingDTO(Boolean destination) {
    this.destination = destination;
}

public ShipmentTracingDTO() {
}

public static void main(String[] args) {
    ArrayList<ShipmentTracingDTO> tracings = new ArrayList<>();
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(false));
    tracings.add(new ShipmentTracingDTO(false));
    ArrayList<ShipmentTracingDTO> newTracings = new ArrayList<>();

// Error coming for ArrayList::new : The constructed object of type ArrayList is 
//incompatible with the descriptor's return type: R

    tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
        left.addAll(right);
        return left;
    });
}

private boolean getDestination() {

    return destination;
}

}

My question is if ArrayList::new doesn't work here, what will work. I tried different variation but none seems to work

3 Answers

Just change it like so,

tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
    left.addAll(right);
});

What you need is a BiConsumer NOT a BinaryOperator. What you are passing above is a BinaryOperator.

Here's an example BinaryOperator.

BinaryOperator<List<Integer>> s = (left, right) -> {
            left.addAll(right);
            return left;
};

As a good engineering practice, always prefer method references to lambdas. So here's the enhanced version using method references in place of lambdas.

tracings.stream().collect(ArrayList::new, List::add, List::addAll);

You seem to be looking for:

tracings.stream()
        .collect(ArrayList::new, 
                 ArrayList::add, 
                 ArrayList::addAll);

which is the same as the lambda representation:

tracings.stream()
        .collect(ArrayList::new, 
                 (left, right) -> left.add(right), 
                 (left, right) -> left.addAll(right)); // notice no 'return'

Reason: The Stream.collect expects a BiConsumer as an argument, which has a accept method with voidreturn type.

I was just trying to create somewhat similar to Collectors.toList() of my own but it doesn't seem to work

While the other answers specify what you've done wrong it's worth noting that if you're trying to create something similar to toList() but at the same time specify the type of list returned then I'd suggest using toCollection which is specifically made for this purpose.

tracings.stream().collect(Collectors.toCollection(ArrayList::new));

although this is no better than:

new ArrayList<>(tracings);

which is shorter and more readable.

Related