Java8中使用Function::identity于Collectors.toMap时出现参数不匹配错误
问题:用Collectors.toMap时,Function::identity为啥会编译报错?
我有一个简单的Person POJO类:
public class Person { private String id; private String name; public Person(String id, String name) { super(); this.id = id; this.name = name; } public String getId() { return id; } public String getName() { return name; } }
我想把一个List<Person>转换成Map<String, Person>,其中key是Person的id属性。于是我写了下面的代码:
import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class CollectorMain { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person("312", "John")); list.add(new Person("454", "Alice")); list.add(new Person("712", "Bob")); Map<String, Person> map = list.stream() .collect( Collectors.toMap(Person::getId, Function::identity) // 这里编译报错 ); System.out.println(map.size()); } }
结果出现了编译错误,错误信息如下:
CollectorMain.java:[14,41] no suitable method found for toMap(Person::getId,Function::identity) method java.util.stream.Collectors.<T,K,U>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>) is not applicable (cannot infer type-variable(s) T,K,U (argument mismatch; incompatible parameter types in method reference)) method java.util.stream.Collectors.<T,K,U>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>,java.util.function.BinaryOperator<U>) is not applicable (cannot infer type-variable(s) T,K,U (actual and formal argument lists differ in length)) method java.util.stream.Collectors.<T,K,U,M>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>,java.util.function.BinaryOperator<U>,java.util.function.Supplier<M>) is not applicable (cannot infer type-variable(s) T,K,U,M (actual and formal argument lists differ in length))
我知道把Function::identity换成lambda表达式p -> p就能解决问题:
Map<String, Person> map = list.stream() .collect( Collectors.toMap(Person::getId, p -> p) );
那有没有办法用Function::identity来实现这个需求呢?
当然可以!问题出在类型推断上
编译器在这里没法自动推断出Function::identity的泛型类型,因为Collectors.toMap的两个参数需要关联同一个输入类型T(也就是Person),但方法引用Function::identity本身是无界的,编译器没法确定它应该接受Person类型的输入。
解决方法就是显式指定泛型类型,有两种方式:
方式一:给Collectors.toMap指定泛型参数
显式声明toMap的三个泛型参数:T=Person,K=String,U=Person:
Map<String, Person> map = list.stream() .collect( Collectors.<Person, String, Person>toMap(Person::getId, Function::identity) );
方式二:给Function.identity()指定泛型参数
直接给identity方法指定泛型,明确它返回的是Person类型的Function:
Map<String, Person> map = list.stream() .collect( Collectors.toMap(Person::getId, Function.<Person>identity()) );
这样编译器就能正确识别类型,编译就不会报错了。
内容的提问来源于stack exchange,提问作者Jmini
相关产品推荐
相关产品推荐

