2015-08-28 10 views
40

Sto provando a convertire i vecchi convenzionali per ogni ciclo fino a java7 in java8 per ogni ciclo per un set di voci di mappa ma sto ricevendo un errore. Ecco il codice che sto cercando di convertire:forEach loop Java 8 per il set di voci Mappa

for (Map.Entry<String, String> entry : map.entrySet()) { 
     System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 
    } 

Ecco i cambiamenti che ho fatto:

map.forEach(Map.Entry<String, String> entry -> { 
     System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 

    }); 

Ho provato a fare anche questo:

Map.Entry<String, String> entry; 
    map.forEach(entry -> { 
     System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 

    }); 

ma l'errore ancora di fronte . L'errore che sto ricevendo per questo è: Firma del Lambda espressione non corrisponde alla firma del metodo di interfaccia funzionale accept(String, String)

risposta

103

Leggi the javadoc: Map<K, V>.forEach() aspetta una BiConsumer<? super K,? super V> come argomento, e la firma del metodo astratto BiConsumer<T, U> è accept(T t, U u).

così si dovrebbe passare un'espressione lambda che prende due ingressi come argomento: la chiave e il valore:

map.forEach((key, value) -> { 
    System.out.println("Key : " + key + " Value : " + value); 
}); 

Il codice potrebbe funzionare se si chiama foreach() sul set di entrata della mappa, non sulla mappa stessa: "? quale versione è più veloce e quale deve utilizzare"

map.entrySet().forEach(entry -> { 
    System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue()); 
}); 
+0

Grande. Ora lavorando entrambi. Ma qual è il modo migliore? In tal caso, le prestazioni sarebbero migliori? @ JBNizet –

+2

La seconda versione forza l'istanza di 'Map.Entry' da creare per ogni voce; il primo ti dà la chiave e il valore senza alcuna istanziazione. Pertanto 'Map.Entry' è un intermediario e puoi evitarlo usando la prima versione. –

+0

Grazie a @MarkoTopolnik ho capito il tuo punto. –

8

Forse il modo migliore per rispondere alle domande come è quello di guardare al codice sorgente:.

map.forEach() - da Map.java

default void forEach(BiConsumer<? super K, ? super V> action) { 
    Objects.requireNonNull(action); 
    for (Map.Entry<K, V> entry : entrySet()) { 
     K k; 
     V v; 
     try { 
      k = entry.getKey(); 
      v = entry.getValue(); 
     } catch(IllegalStateException ise) { 
      // this usually means the entry is no longer in the map. 
      throw new ConcurrentModificationException(ise); 
     } 
     action.accept(k, v); 
    } 
} 

javadoc

map.entrySet() foreach() - da Iterable .java

default void forEach(Consumer<? super T> action) { 
    Objects.requireNonNull(action); 
    for (T t : this) { 
     action.accept(t); 
    } 
} 

javadoc

Questo rivela immediatamente che map.forEach() utilizza anche Map.Entry internamente. Quindi non mi aspetto alcun beneficio in termini di prestazioni nell'uso di map.forEach() su map.entrySet(). ForEach(). Quindi nel tuo caso la risposta dipende molto dal tuo gusto personale :)

Per l'elenco completo delle differenze fai riferimento ai link javadoc forniti. Buona programmazione!

4

È possibile utilizzare il seguente codice per il vostro requisito

map.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));