2017-10-10 166 views
6

以下代码错误映射

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

通过的IntelliJ转换为:

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

可缩短至

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

的2个版本别编译。

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

Incompatible types.
Required: int
Found: java.lang.Object

编译器会抱怨:

Error:(35, 17) java: method collect in interface java.util.stream.IntStream cannot be applied to given types;
required: java.util.function.Supplier,java.util.function.ObjIntConsumer,java.util.function.BiConsumer
found: java.util.stream.Collector>
reason: cannot infer type-variable(s) R
(actual and formal argument lists differ in length)

任何人都可以解释,为什么?

+0

什么'值',你能否包括它的声明?对IntelliJ的建议,似乎也不一致。只需在声明和循环之间放置一个print map语句即可。它不会建议你*取代收藏*了。 – nullpointer

+1

String [] values = ... – msayag

+0

我想'Collector's不支持原语,这可能是为什么lambda转换为'Object',因为'boxed()'修复了它。 –

回答

2

对智慧的建议如何在那里工作不太确定,似乎并不一致。只要把申报和环路之间的

System.out.print(map); 

语句,然后它不会建议你用收集任何进一步的替换。


当使用IntStream#collect,编译失败对于实现collect方法需要三个指定的参数为可视错误以及同时

Collectors.toMap(i -> "X" + i, i -> values[i]) 

会导致只有一个参数的原因类型Collector


更好地表达转换方法是,虽然以

  • 要么使用forEach

    Map<String, Object> map; 
    IntStream.range(0, values.length).forEach(i -> map.put("X" + i, values[i])); 
    
  • 或者使用boxed()IntStream转换为Stream<Integer>为: -

    Map<String, Object> map = IntStream.range(0, values.length).boxed() 
          .collect(Collectors.toMap(i -> "X" + i, i -> values[i], (a, b) -> b)); 
    
  • 或者通过@Holger的建议,你能避免使用的forEach和拳击开销和修改结构,以利用IntStream.collect三ARG变异为: -

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

我会使用第一个。第二个,用'boxed'将导致'Integer'和int之间的盒子和解除盒子过多。 – Shirkam

+0

虽然你的解决方案是有效的,但他们不回答我的问题:为什么不编译? – msayag

+0

@msayag编辑。虽然考虑日志是不言自明的。另一方面,使用boxed将'IntStream'转换为'Stream',并且'collect'在该类中被重载以接受您的'Collector'传递。 – nullpointer