收集IntStream进行映射时出错

msa*_*yag 6 java javac intellij-idea java-8 java-stream

以下代码

String[] values = ...
.... 
Map<String, Object> map = new HashMap<>();
for (int i = 0; i < values.length; i++) {
    map.put("X" + i, values[i]);
}
Run Code Online (Sandbox Code Playgroud)

由IntelliJ转换为:

Map<String, Object> map = IntStream.range(0, values.length)
        .collect(Collectors.toMap(
                i -> "X" + i,
                i -> values[i],
                (a, b) -> b));
Run Code Online (Sandbox Code Playgroud)

这可以缩短为

Map<String, Object> map = IntStream.range(0, values.length)
            .collect(Collectors.toMap(
                    i -> "X" + i,
                    i -> values[i]));
Run Code Online (Sandbox Code Playgroud)

2个流版本无法编译.

IntelliJ,暗示值[i]中的i存在问题:

不兼容的类型.
必需:int
Found:java.lang.Object

编译器抱怨:

错误:(35,17)java:接口java.util.stream.IntStream中的方法collect不能应用于给定的类型;
required:java.util.function.Supplier,java.util.function.ObjIntConsumer,java.util.function.BiConsumer
found:java.util.stream.Collector>
reason:无法推断类型变量R
(实际和正式)参数列表长度不同)

有谁能解释为什么?

Nam*_*man 5

不太确定 intelliJ 的建议如何在那里工作,这似乎不一致。只要放一个

System.out.print(map);
Run Code Online (Sandbox Code Playgroud)

声明和循环之间的语句,然后它不会建议您进一步替换为 collect


使用 时IntStream#collect,编译失败,因为collect方法的实现需要三个指定的参数在错误中可见,而

Collectors.toMap(i -> "X" + i, i -> values[i])
Run Code Online (Sandbox Code Playgroud)

将导致只有一个类型的参数Collector


转换表达式的更好方法是

  • 要么使用 forEach

    Map<String, Object> map;
    IntStream.range(0, values.length).forEach(i -> map.put("X" + i, values[i]));
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者使用boxed()在转换IntStreamStream<Integer>如下: -

    Map<String, Object> map = IntStream.range(0, values.length).boxed()
               .collect(Collectors.toMap(i -> "X" + i, i -> values[i], (a, b) -> b));
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者按照@Holger 的建议,您可以避免使用 forEach 和装箱开销并修改构造以使用IntStream.collect三参数变体:-

    Map<String, Object> map = IntStream.range(0, values.length)
               .collect(HashMap::new, (m,i) -> m.put("X"+i,values[i]), Map::putAll);
    
    Run Code Online (Sandbox Code Playgroud)

  • 使用三参数变量:`Map&lt;String, Object&gt; map = IntStream.range(0, values.length) .collect(HashMap::new, (m,i) -&gt; m.put("X"+i) ,values[i]), Map::putAll);` 避免了装箱开销,而没有 `forEach` 代码味道。 (2认同)