Java 8 Streams:为什么Collectors.toMap的行为与使用通配符的泛型不同? [英] Java 8 Streams: why does Collectors.toMap behave differently for generics with wildcards?

查看:306
本文介绍了Java 8 Streams:为什么Collectors.toMap的行为与使用通配符的泛型不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你有一个 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));

编译器抱怨调用 number.intValue()
lockquote
Test.java:找不到符号

符号:方法intValue ()

location:java.lang.Object类型的变量数

从编译器错误显然lambda中的 number 被视为 Object ,而不是作为 Number



所以,现在我的问题:


  • 当收集 List 的通配符版本,为什么它不像 List的非通配符版本一样工作?

  • 为什么lambda中的数字变量被认为是 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 the List can be of type Integer, Double etc. When you declare such a List 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 the List and collect it all to a Map using the Collectors.toMap (obviously the code below is just an example to illustrate the problem). Lets start off by streaming the numberList:

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.Object

From the compiler error it is obvious that the number in the lambda is treated as an Object instead of as a Number.

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 the List?
  • Why is the number variable in the lambda considered to be an Object instead of a Number?

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆