Search code examples
javaarraylistjava-8java-streamcollectors

Valid Supplier for collect method of stream


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


Solution

  • 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);