user3103957
user3103957

Reputation: 848

Custom collector throwing error in java stream

I am trying to write a custom collector in java stream.

I have a employee class which has id, name and salary. Each attribute has its own getter and setter methods. I create an arraylist which has several instances of employee objects added in it. Then I create a stream out of the arraylist and I try to collect the stream objects in a hashmap. Note: The combiner is syntactically correct evhentoug it does not make sense.

The compiler keeps saying that the arguments are not correct. I am not sure what is the mistake I am doing.Can any one please help me.

Code of the Employee class:

public class Employee { 
    private int id;
    private String name;
    private int salary;

    public Employee(int id,String name,int salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }   
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public int getSalary() {
        return salary;
    }   
}

Code where I create an arraylist and custom collector:

public class ListTest {

    public static void main(String[] args) {

        Employee e1 = new Employee (100,"R1",2000);
        Employee e2 = new Employee (200,"R2",4000);
        Employee e3 = new Employee (300,"R3",6000);
        Employee e4 = new Employee (400,"R4",7000);

        ArrayList<Employee> al = new ArrayList<>();
        al.add(e1);
        al.add(e2);
        al.add(e3);
        al.add(e4);

        al.stream().collect(Collector.of(
            new HashMap<Integer, Employee>(),
            (HashMap<Integer, Employee> a, Employee b) -> {
                a.put(b.getId(), b);
                return a;
            },
            (HashMap<Integer, Employee> c, HashMap<Integer, Employee> d) -> c,
            Function.identity())
        );
    }
}

The error I am getting:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
    The method of(Supplier<R>, BiConsumer<R,T>, BinaryOperator<R>, Collector.Characteristics...) in the type Collector is not applicable for the arguments (HashMap<Integer,Employee>, (HashMap<Integer, Employee> a, Employee b) -> {}, (HashMap<Integer, Employee> c, HashMap<Integer, Employee> d) -> {}, Function<Object,Object>)
    Incompatible type specified for lambda expression's parameter a
    Incompatible type specified for lambda expression's parameter b
    Void methods cannot return a value
    Incompatible type specified for lambda expression's parameter c
    Incompatible type specified for lambda expression's parameter d
    Type mismatch: cannot convert from HashMap<Integer,Employee> to R
    Type mismatch: cannot convert from Function<Object,Object> to Collector.Characteristics

Upvotes: 2

Views: 484

Answers (1)

Marc Baumbach
Marc Baumbach

Reputation: 10473

There are two problems, your first argument is not a valid Supplier function, it's simply constructing a HashMap at the time of calling the of method. In addition to that, the second argument to the Collector.of takes a BiConsumer, so it shouldn't return a value since it has a void return signature. Try something like this:

Map<Integer, Employee> employees = al.stream().collect(Collector.of(
   () -> new HashMap<>(),
   (HashMap<Integer, Employee> a, Employee b) -> {
       a.put(b.getId(), b);
   },
   (HashMap<Integer, Employee> c, HashMap<Integer, Employee> d) -> {
       c.putAll(d);
       return c;
   },
   Function.identity()
));

I thought I'd also offer a simpler way of accomplishing this without needing to write a custom Collector:

al.stream().collect(Collectors.toMap(Employee::getId, Function.identity()));

This will result in a Map<Integer, Employee> object that maps ID to the Employee itself.

Upvotes: 3

Related Questions