2017-10-10 15 views
6

Le code suivantErreur lors de la collecte IntStream vers la carte

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

est converti par IntelliJ à:

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

qui peut être raccourcie à

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

Les 2 versions de flux n » t compiler.

IntelliJ, conseils qu'il ya un problème avec l'i des valeurs [i]:

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

Le compilateur se plaint:

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)

Quelqu'un peut-il expliquer pourquoi?

+0

ce qui est des valeurs ' ', pourriez-vous inclure sa déclaration aussi. Aussi sur la suggestion d'IntelliJ, semble incohérent. Mettez simplement une instruction print 'map' entre la déclaration et la boucle. Il ne vous suggérera plus de * remplacer par collect *. – nullpointer

+1

String [] values ​​= ... – msayag

+0

J'imagine que 'Collector's ne supporte pas les primitives, et c'est peut-être pourquoi les lambdas sont convertis en' Object', parce que 'boxed()' le corrige. –

Répondre

2

Pas très sûr de savoir comment la suggestion de intelliJ fonctionnerait là, il semble incohérent. Il suffit de mettre une déclaration

System.out.print(map); 

entre la déclaration et la boucle et il ne vous suggère avec Replace Collect plus loin.


Lorsque vous utilisez le IntStream#collect, la compilation échoue pour la raison que la mise en œuvre de la méthode collect attend trois arguments spécifiés comme visibles dans l'erreur et alors que le

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

entraînerait qu'un seul argument de type Collector.


Une meilleure façon de convertir l'expression serait bien à

  • soit utiliser forEach

    Map<String, Object> map; 
    IntStream.range(0, values.length).forEach(i -> map.put("X" + i, values[i])); 
    
  • Ou utilisez boxed() pour convertir le IntStream-Stream<Integer> comme: -

    Map<String, Object> map = IntStream.range(0, values.length).boxed() 
          .collect(Collectors.toMap(i -> "X" + i, i -> values[i], (a, b) -> b)); 
    
  • Ou comme suggéré par @Holger, vous pouvez éviter d'utiliser forEach et les frais généraux de boxe et de modifier la construction à utiliser la IntStream.collect trois arg variante comme: -

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

Je voudrais utiliser le premier. Le second, avec ce 'boxed' conduira à trop de boîtes et unboxes entre' Integer' et int. – Shirkam

+0

Alors que vos solutions sont valides, elles ne répondent pas à ma question: pourquoi ne compile-t-elle pas? – msayag

+0

@msayag Modifié. Considérait le journal comme auto-explicatif cependant. En utilisant boxed, d'autre part convertit le 'IntStream' en' Stream 'et le 'collect' est surchargé dans cette classe pour accepter votre' Collector' passé. – nullpointer