英文:
Collectors.toMap with method reference compiles but not with identity function lambda
问题
下面的语句给我一个错误,但另一种形式可以工作,有什么区别
LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, x-> x, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
下面的可以工作
LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, Employee::getId, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
英文:
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));
答案1
得分: 1
Collectors.toMap的前两个参数分别是键映射器和值映射器。
keyMapper = Employee::getName 等同于 keyMapper = x -> x.getName(),意味着结果映射的键将是员工的名称属性(String)。
valueMapper = x -> x 意味着结果映射的值将是员工本身。只有当结果类型为 LinkedHashMap<String, Employee> 而不是 LinkedHashMap<String, Integer> 时才可能成功,这也是为什么它失败的原因。
valueMapper = Employee::getId 等同于 valueMapper = x -> x.getId(),意味着结果映射的值将是员工的id属性(Integer)。这与结果类型 LinkedHashMap<String, Integer> 兼容。
也就是说,根据预期的结果,以下两种方式都是正确的:
// 从名称映射到员工
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));
// 从名称映射到员工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));
英文:
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));
答案2
得分: 0
显然这段代码应该是:
LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, x -> x.getId(), (oldValue, newValue) -> old, LinkedHashMap::new));
注意区别在于 x-> x.getId() 而不是 x-> x。
英文:
obviously this:
LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, x-> x, (oldValue, newValue) -> old, LinkedHashMap::new));
should be
LinkedHashMap<String, Integer> collect = employees.stream().sorted(Comparator.comparing(Employee::getName).reversed()).collect(Collectors.toMap(Employee::getName, x-> x.getId(), (oldValue, newValue) -> old, LinkedHashMap::new));
note the x-> x.getId() difference insead of x-> x
答案3
得分: 0
查看Collection.toMap函数定义,来自docs.oracle的链接:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-java.util.function.BinaryOperator-java.util.function.Supplier-
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)。
如果您想创建一个LinkedHashMap<String, Integer>,那么valueMapper应该提供一个Integer类型的对象,但在第一个示例中x->x并不是这种情况,它是一个接受Employee对象并返回一个Employee的lambda表达式。而Employee::getId可以正常工作,因为它返回了正确类型的对象,即Integer。
英文:
taking a look to the function definition of Collection.toMap from docs.oracle:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-java.util.function.BinaryOperator-java.util.function.Supplier-
toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier).
Since you want to create a LinkedHashMap<String, Integer> than the valueMapper should provide an object of type Integer which is not the case in the first example x->x which is a lambda taking an Employee object and returns an Employee as well, whereas Employee::getId works fine since it returns an object of the correct type which is Integer .
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论