Collectors.toMap无法编译

8
这段代码无法编译。
List<String> pairs = new ArrayList<>();
System.out.println(pairs.stream().collect(Collectors.toMap(x -> x.split("=")[0], x -> x.split("=")[1])));

编译错误是:方法split(String)对类型Object未定义 在System.out.println(pairs.stream().collect(Collectors.toMap(x -> x.split("=")[0], x -> x.split("=")[1])));处出错

但这个可以编译成功。

List<String> pairs = new ArrayList<>();
Map<String,String> map = pairs.stream().collect(Collectors.toMap(x -> x.split("=")[0], x -> x.split("=")[1]));
System.out.println(map);

能有人解释一下为什么吗?

更多信息

这是在Intellij 12、JDK1.8.0_11和Windows 64位系统下发生的。


2
你好,以下是翻译内容:“两个版本在我的jdk1.8.0_20上都可以编译和运行。你使用的jdk版本是什么?” - Misha
无法重现 - 你可能使用的是旧版本的jdk或者不同的编译器(比如eclipse)。 - assylias
@所有人:这个问题可以在Eclipse中重现。我正在使用新的Luna版本。Eclipse编译器显示了这个编译器错误。使用简单的“javac…”命令编译没有问题。 - Seelenvirtuose
据我所知,一些编译器在正确推断泛型类型方面存在问题,尤其是在像第一个代码块中的情况下。这可能解释了为什么有些人无法重现该错误。你可以尝试在第一个代码块中使用Collectors.<String, String, String>toMap(...) - Thomas
2个回答

5

我假设您正在使用一个IDE(如Eclipse)。例如,Eclipse使用自己的编译器,而不使用“javac”命令(来自JDK)。

所以,我可以重现您在Eclipse中遇到的问题。但只需在命令行上使用“javac”编译此代码即可正常工作。

问题非常简单:Eclipse编译器无法推断collect方法参数的String类型。因此,它只推断出Object类型(因为这是编译器可以安全地假定的类型)。而且Object不知道split方法。

您可以通过在lambda内显式声明类型来强制编译器了解String

List<String> pairs = new ArrayList<>();
System.out.println(pairs.stream().collect(Collectors.toMap((String x) -> x.split("=")[0], x -> x.split("=")[1])));

... 或通过明确声明泛型 toMap 方法的正确类型:

List<String> pairs = new ArrayList<>();
System.out.println(pairs.stream().collect(Collectors.<String, String, String> toMap(x -> x.split("=")[0], x -> x.split("=")[1])));

1

IntelliJ的不同版本在源代码编辑器中显示不同(只有红色下划线)。代码应该能够成功地通过JDK编译。

对于您的代码,IntelliJ 13是可以的。 IntelliJ 12 在支持lambda表达式方面存在问题。当使用lambda表达式时,我也遇到了两个版本的IntelliJ之间类似的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接