Search code examples
javajava-stream

Collectors.toMap with method reference compiles but not with identity function lambda


I have an ArrayList which I'm trying to convert to a LinkedHashMap. The below statement gives me an error but another form works what is the difference

Below give an error Bad return type in lambda expression: U cannot be converted to Employee

LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, x-> x, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

Below work

 LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, Employee::getId, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

Solution

  • The first two arguments of the Collectors.toMap are a key mapper and a value mapper, respectively.

    keyMapper = Employee::getName is equivalent to keyMapper = x -> x.getName() and means that the key of the resulting map will be the name attribute of the employee (String).

    valueMapper = x -> x means that the value of the resulting map will be the employee itself. That would only be possible if the result was of type LinkedHashMap<String, Employee> instead of LinkedHashMap<String, Integer>, and that's why it fails.

    valueMapper = Employee::getId is equivalent to valueMapper = x -> x.getId() and means that the value of the resulting map will be the id attribute of the employee (Integer). This is compatible with the result type LinkedHashMap<String, Integer>.

    That said, both the below are correct depending on the intended outcome:

    // map from name to Employee
    LinkedHashMap<String, Employee> collect = employees.stream()
            .sorted(Comparator.comparing(Employee::getName).reversed())
            .collect(Collectors.toMap(x -> x.getName(), x -> x, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
    
    // map from name to Employee Id
    LinkedHashMap<String, Integer> collect = employees.stream()
            .sorted(Comparator.comparing(Employee::getName).reversed())
            .collect(Collectors.toMap(Employee::getName, Employee::getId, (oldValue, newValue) -> oldValue, LinkedHashMap::new));