Java 8 Streams:为什么Collectors.toMap的行为与使用通配符的泛型不同? [英] Java 8 Streams: why does Collectors.toMap behave differently for generics with wildcards?
问题描述
List
的数字。 List
中的值可以是整数
, Double
>等。当你声明这样一个 List
时,可以使用通配符(?
)或者没有通配符。 最终列表< Number> numberList = Arrays.asList(1,2,3D);
最终列表< ;?扩展Number> wildcardList = Arrays.asList(1,2,3D);
所以,现在我想要 stream
over将 List 和
collect
全部转换为 Map
Collectors.toMap
(显然下面的代码仅仅是一个例子来说明问题)。让我们开始流式传输 numberList
:
final List< Number> numberList = Arrays.asList(1,2,3D,4D);
numberList.stream()。collect(Collectors.toMap(
//这里我可以调用number.intValue() - 对象(数字)被视为一个数字
number - > Integer.valueOf(number.intValue()),
number - > number));
但是,我无法对 wildcardList
:
final List< ;?扩展Number> wildCardList = Arrays.asList(1,2,3D);
wildCardList.stream()。collect(Collectors.toMap(
//为什么number被当作Object而不是数字?
number - > Integer.valueOf(number。 intValue()),
number - > number));
编译器抱怨调用 从编译器错误显然lambda中的 所以,现在我的问题: number.intValue()$
lockquote
Test.java:找不到符号
符号:方法intValue ()
location:java.lang.Object类型的变量数
number
被视为 Object
,而不是作为 Number
。
List
的通配符版本,为什么它不像 List的非通配符版本
一样工作?
数字
变量被认为是 Object
而不是号码
?
类型推断不正确。如果您明确提供了type参数,它将按预期工作:
List< ;?扩展Number> wildCardList = Arrays.asList(1,2,3D);
wildCardList.stream()。collect(Collectors。< Number,Integer,Number> toMap(
number - > Integer.valueOf(number.intValue()),
number - > ;数字));
这是一个已知的javac错误:推理不应将捕获变量映射到上限。根据Maurizio Cimadamore的说法,这个状态是,bb
$ b
一次修复试图被撤销,因为它在8次破案,所以我们在做完全面的事情的时候,他在8点进行了更为保守的修正。
。 (感谢
JoelBorggrén-Franck 指引我朝着正确的方向。)Assume that you have a
List
of numbers. The values in theList
can be of typeInteger
,Double
etc. When you declare such aList
it is possible to declare it using a wildcard (?
) or without a wildcard.final List<Number> numberList = Arrays.asList(1, 2, 3D); final List<? extends Number> wildcardList = Arrays.asList(1, 2, 3D);
So, now I want to
stream
over theList
andcollect
it all to aMap
using theCollectors.toMap
(obviously the code below is just an example to illustrate the problem). Lets start off by streaming thenumberList
:final List<Number> numberList = Arrays.asList(1, 2, 3D, 4D); numberList.stream().collect(Collectors.toMap( // Here I can invoke "number.intValue()" - the object ("number") is treated as a Number number -> Integer.valueOf(number.intValue()), number -> number));
But, I can not do the same operation on the
wildcardList
:final List<? extends Number> wildCardList = Arrays.asList(1, 2, 3D); wildCardList.stream().collect(Collectors.toMap( // Why is "number" treated as an Object and not a Number? number -> Integer.valueOf(number.intValue()), number -> number));
The compiler complains on the call to
number.intValue()
with the following message:Test.java: cannot find symbol
symbol: method intValue()
location: variable number of type java.lang.ObjectFrom the compiler error it is obvious that the
number
in the lambda is treated as anObject
instead of as aNumber
.So, now to my question(s):
- When collecting the wildcard version of the
List
, why is it not working like the non-wildcard version of theList
?- Why is the
number
variable in the lambda considered to be anObject
instead of aNumber
?解决方案It's the type inference that doesn't get it right. If you provide the type argument explicitly it works as expected:
List<? extends Number> wildCardList = Arrays.asList(1, 2, 3D); wildCardList.stream().collect(Collectors.<Number, Integer, Number>toMap( number -> Integer.valueOf(number.intValue()), number -> number));
This is a known javac bug: Inference should not map capture variables to their upper bounds. The status, according to Maurizio Cimadamore,
a fix was attempted then backed out as it was breaking cases in 8, so we went for a more conservative fix in 8 while doing the full thing in 9
Apparently the fix has not yet been pushed. (Thanks to Joel Borggrén-Franck for pointing me in the right direction.)
这篇关于Java 8 Streams:为什么Collectors.toMap的行为与使用通配符的泛型不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!