forEach Schleife Java 8 für Karteneintragssatz

82

Ich versuche, alte konventionelle für jede Schleife bis Java7 in Java8 für jede Schleife für einen Karteneintragssatz zu konvertieren, aber ich erhalte eine Fehlermeldung. Hier ist der Code, den ich konvertieren möchte:

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

Hier sind die Änderungen, die ich vorgenommen habe:

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

   }); 

Ich habe es auch versucht:

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

   });

Aber immer noch vor Irrtum. Der Fehler, den ich dafür bekomme, ist: Die Signatur des Lambda-Ausdrucks stimmt nicht mit der Signatur der Funktionsschnittstellenmethode übereinaccept(String, String)

Siddharth Sachdeva
quelle

Antworten:

191

Lesen Sie das javadoc : Map<K, V>.forEach()erwartet ein BiConsumer<? super K,? super V>as-Argument und die Signatur der BiConsumer<T, U>abstrakten Methode lautet accept(T t, U u).

Sie sollten ihm also einen Lambda-Ausdruck übergeben, der zwei Eingaben als Argument verwendet: den Schlüssel und den Wert:

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

Ihr Code würde funktionieren, wenn Sie forEach () für den Eintragssatz der Karte und nicht für die Karte selbst aufrufen würden:

map.entrySet().forEach(entry -> {
    System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}); 
JB Nizet
quelle
Toll. Jetzt arbeiten beide. Aber welcher ist ein besserer Weg? In welchem ​​Fall wäre die Leistung besser? @ JBNizet
Siddharth Sachdeva
2
Die zweite Version erzwingt die Map.EntryErstellung einer Instanz für jeden Eintrag. Der erste gibt Ihnen Schlüssel und Wert ohne Instanziierung. Daher Map.Entryist ein Mittelsmann und Sie können dies mit der ersten Version vermeiden.
Marko Topolnik
5
@ Marko Topolnik: Bei den meisten MapImplementierungen sind die Map.EntryInstanzen bereits vor der Iteration vorhanden und müssen nicht erstellt werden. Wenn Sie sich jedoch nicht mit Map.Entryder Aktion befassen müssen, ist dies ein Gewinn für die Lesbarkeit und bietet ein geringes Potenzial für eine bessere Leistung, da keine zusätzlichen Methodenaufrufe erforderlich sind, um den Schlüssel und den Wert abzurufen.
Holger
2
@Holger Ich werde Ihre stillschweigende Implikation betonen: für die meisten, aber nicht alle , MapImplementierungen , die wahr ist, ConcurrentHashMapein wichtiges Gegenbeispiel zu sein.
Marko Topolnik
1
@ Marko Topolnik: Aber wenn Sie über eine ganze Iteration iterieren ConcurrentHashMap, sind temporäre Eintragsinstanzen das Letzte, worüber Sie sich Sorgen machen müssen. Trotzdem sind wir uns einig, es map.forEach((key, value) -> …);trotzdem vorzuziehen ...
Holger
13

Vielleicht der beste Weg, um die Fragen zu beantworten wie "Welche Version ist schneller und welche soll ich verwenden?" ist auf den Quellcode zu schauen:

map.forEach () - von 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 () - von Iterable.java

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

Javadoc

Dies zeigt sofort , dass map.forEach () wird auch mit Map.Entry intern. Daher würde ich keinen Leistungsvorteil bei der Verwendung von map.forEach () gegenüber map.entrySet (). ForEach () erwarten . In deinem Fall hängt die Antwort also wirklich von deinem persönlichen Geschmack ab :)

Die vollständige Liste der Unterschiede finden Sie unter den bereitgestellten Javadoc-Links. Viel Spaß beim Codieren!

Evgeny Tugarev
quelle
7

Sie können den folgenden Code für Ihre Anforderung verwenden

map.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));
Shridhar Sangamkar
quelle
2
Diese Antwort ist identisch mit einem Teil der Antwort, die JB Nizet 2 Jahre zuvor gegeben hat, und enthält keine zusätzlichen nützlichen Informationen.
Madbreaks
0
HashMap<String,Integer> hm = new HashMap();

 hm.put("A",1);
 hm.put("B",2);
 hm.put("C",3);
 hm.put("D",4);

 hm.forEach((key,value)->{
     System.out.println("Key: "+key + " value: "+value);
 });
vaibhav1111
quelle
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu. Dies wird anderen helfen, Ihre Antwort an ihre eigenen Bedürfnisse anzupassen. Aus der Überprüfung .
Wai Ha Lee
0

Stream-API

public void iterateStreamAPI(Map<String, Integer> map) {
    map.entrySet().stream().forEach(e -> System.out.println(e.getKey() + ":"e.getValue()));
}
vivek
quelle
0
String ss = "Pawan kavita kiyansh Patidar Patidar";
    StringBuilder ress = new StringBuilder();
    
    Map<Character, Integer> fre = ss.chars().boxed()
            .collect(Collectors.toMap(k->Character.valueOf((char) k.intValue()),k->1,Integer::sum));
    
      //fre.forEach((k, v) -> System.out.println((k + ":" + v)));
    
    fre.entrySet().forEach(e ->{
            //System.out.println(e.getKey() + ":" + e.getValue());
            //ress.append(String.valueOf(e.getKey())+e.getValue());
        }); 

    fre.forEach((k,v)->{
        //System.out.println("Item : " + k + " Count : " + v);
        ress.append(String.valueOf(k)+String.valueOf(v));
    });
    
    System.out.println(ress.toString());
Pawan Patidar
quelle
Während dieses Code-Snippet die Lösung sein kann, hilft das Hinzufügen einer Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage in Zukunft für Leser beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Neo Anderson