Ashishkumar Singh
Ashishkumar Singh

Reputation: 3600

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

Upvotes: 4

Views: 1284

Answers (3)

Naman
Naman

Reputation: 31958

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.

Upvotes: 5

Ravindra Ranwala
Ravindra Ranwala

Reputation: 21124

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

Upvotes: 6

Ousmane D.
Ousmane D.

Reputation: 56443

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.

Upvotes: 1

Related Questions