Iterator<Entry<Integer,Double>>无法转为通配符上限迭代器原因及修复
问题原因与修复方案
问题根源
Java泛型具备不变性,Iterator<Entry<Integer, Double>> 和 Iterator<Entry<? extends Integer, ? extends Double>> 是完全不兼容的两类泛型:即使Entry<Integer, Double>本身是Entry<? extends Integer, ? extends Double>的子类型,也不会让二者对应的Iterator类型存在继承关系。
Guava的ImmutableMap.Builder.putAll方法签名要求入参为Iterable<? extends Entry<? extends K, ? extends V>>,你直接通过lambda返回Iterator<Entry<Integer, Double>>时,Java无法自动完成泛型通配符的推导匹配,因此抛出类型转换错误。
修复方案
两种无需额外实现collect方法的修复方式可选:
- 方案一:显式转换lambda的目标类型,改动最小
直接给lambda强转为符合putAll参数要求的Iterable类型即可:// 示例代码修复 ImmutableMap.<Integer, Double>builder().putAll((Iterable<? extends Entry<? extends Integer, ? extends Double>>) () -> list.stream().iterator()); - 方案二:构造Entry时显式声明带通配符的类型
在map转换时将生成的Entry强转为带通配符的类型,让Iterator的返回类型自动匹配方法签名要求,类型推导更友好:// 实际业务代码修复 ImmutableList<Integer> numberList = ImmutableList.of(2,4,8,12,16,24,32); ImmutableMap.<Integer, Double>builder().putAll(() -> numberList.stream().map(num -> (Entry<? extends Integer, ? extends Double>) new AbstractMap.SimpleEntry<>(num, Math.sqrt(num))).iterator());
内容的提问来源于stack exchange,提问作者anynymouse
相关产品推荐
相关产品推荐

