方法签名解密
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return new CollectorImpl<>(HashMap::new,
uniqKeysMapAccumulator(keyMapper, valueMapper),
uniqKeysMapMerger(),
CH_ID);
}
类型参数角色:
-
T:流元素的类型(输入类型) -
K:结果Map键的类型 -
U:结果Map值的类型
重点这里的T是在创建stream流的时候已经确认了,如下代码,这里的stream方法是返回了个Stream对象并且包含了泛型
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
类型参数绑定过程:
-
T的确定:由流元素的类型决定 -
K的确定:由keyMapper的返回类型决定 -
U的确定:由valueMapper的返回类型决定
实际应用示例
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 30)
);
Map<String, Integer> ageMap = people.stream()
.collect(Collectors.toMap(
Person::getName, // Function<Person, String>
Person::getAge // Function<Person, Integer>
));
类型推断过程:
-
T=Person(来自people.stream()) -
K=String(来自Person::getName返回类型) -
U=Integer(来自Person::getAge返回类型) -
最终返回
Collector<Person, ?, Map<String, Integer>>
Lambda表达式的类型解析
Lambda到函数式接口的转换
// Lambda表达式
person -> person.getName()
// 等价于
new Function<Person, String>() {
@Override
public String apply(Person person) {
return person.getName();
}
}
类型推断机制
Java编译器通过目标类型推断机制确定Lambda类型:
-
根据上下文(方法参数位置)确定目标类型
-
根据目标类型(
Function)推断参数类型和返回类型 -
验证Lambda体是否符合返回类型要求
复杂场景类型推断
Map<Long, String> idToName = persons.stream()
.collect(Collectors.toMap(
p -> p.getId(), // 编译器推断为Function<Person, Long>
p -> p.getLastName() + " " + p.getFirstName() // Function<Person, String>
));
底层实现解析
uniqKeysMapAccumulator方法
private static <T, K, U> BiConsumer<Map<K, U>, T>
uniqKeysMapAccumulator(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return (map, element) -> {
K key = keyMapper.apply(element); // 应用keyMapper
U value = valueMapper.apply(element); // 应用valueMapper
// 检查键冲突
if (map.put(key, value) != null) {
throw new IllegalStateException("Duplicate key " + key);
}
};
}
992

被折叠的 条评论
为什么被折叠?



