Frage an java, hashmap, loops, iteration – Durch eine HashMap iterieren [duplizieren]

3059

Mögliche Duplikate:
Wie kann jeder Eintrag in einer 'Map' effizient durchlaufen werden?

Was ist die beste Methode, um die Elemente in a zu durchlaufen?HashMap?

In Java 8 mit Lambda-Ausdruck:stackoverflow.com/a/25616206/1503859 Nitin Mahesh
Wie hat dies eine höhere Punktzahl als die Frage, von der es ein Duplikat ist? immibis
Prüfe die Antwort :stackoverflow.com/a/53497541/5756557 anandchaugule
@immibis wahrscheinlich, weil viele Leute HashMaps instinktiv verwenden, ohne andere Kartenimplementierungen in Betracht zu ziehen. Wenn sie dann unweigerlich feststecken und versuchen, über ihre HashMap zu iterieren, geben sie "Durch eine HashMap iterieren" in Google ein und führen sie direkt hierher. Dean Wild
Ich muss die Schlüssel und die Werte erhalten und sie einem mehrdimensionalen Array hinzufügen burntsugar

Deine Antwort

7   die antwort
115
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}
Ist param der Name der HashMap? c-an
@ChanjungKim Ja, es ist der Name der HashMap heman123
4383

können Sie die durchlaufenkeySet() der Karte:

Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

Wenn Sie nur die Werte benötigen, verwenden Sievalues():

for (Object value : map.values()) {
    // ...
}

Wenn Sie zum Schluss sowohl den Schlüssel als auch den Wert möchten, verwenden SieentrySet():

for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
    // ...
}

Eine Einschränkung: Wenn Sie Elemente während der Iteration entfernen möchten, müssen Sie dies über einen Iterator tun (sieheAntwort von karim79). Das Ändern der Artikelwerte ist jedoch in Ordnung (sieheMap.Entry).

Da kommt die Karte nicht unterIterator Klasse, wie in der ersten Lösung hat die Person Iterator verwendet? Rishabh Agarwal
@MarcoSulla Performance-Fragen wie diese hängen davon ab, dass Sie in wichtigen Fällen messen und sehen sollten. Es ist wahrscheinlich, dass mitentrySet ist schneller, da nicht bei jedem Eintrag nachgeschlagen werden muss. Die Umsetzung des BesonderenMap bestimmt, welcher Weg besser ist und um wie viel. Der GC-Druck zu diesem Zeitpunkt könnte ebenfalls ein Faktor sein. doug65536
Verwenden Sie zwei Iteratoren. In der akzeptierten Antwort finden Sie ein Beispiel für die Verwendung eines Iterators. harto
Ein weiterer wichtiger Punkt: Die von keySet () und Collection zurückgegebenen Werte () werden beide von der ursprünglichen Map unterstützt. Das heißt, wenn Sie Änderungen daran vornehmen, werden diese in der Map wiedergegeben. Beide Methoden unterstützen jedoch nicht die Methoden add () und addAll (), dh Sie können dem Set oder dem neuen Wert keinen neuen Schlüssel hinzufügen in der Sammlung. sactiw
85

Sie können die Einträge in a durchlaufenMap In vielen Wegen. Holen Sie sich jeden Schlüssel und Wert wie folgt:

Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
    System.out.println("Key " + e.getKey());
    System.out.println("Value " + e.getValue());
}

Oder Sie können die Liste der Schlüssel mit abrufen

Collection<?> keys = map.keySet();
for(Object key: keys){
    System.out.println("Key " + key);
    System.out.println("Value " + map.get(key));
}

Wenn Sie nur alle Werte abrufen möchten und sich nicht mit den Schlüsseln befassen, können Sie Folgendes verwenden:

Collection<?> values = map.values();
787

Über eine Karte in Java iterieren:

Es gibt verschiedene Möglichkeiten, über a zu iterierenMap in Java. Lassen Sie uns die gebräuchlichsten Methoden durchgehen und ihre Vor- und Nachteile untersuchen. Da alle Karten in Java die Kartenschnittstelle implementieren, funktionieren die folgenden Techniken für jede Kartenimplementierung (HashMap, TreeMap, LinkedHashMap, Hashtable, usw.)

Methode 1: Durchlaufen von Einträgen mit einer For-Each-Schleife.

Dies ist die häufigste Methode und in den meisten Fällen vorzuziehen. Es sollte verwendet werden, wenn Sie sowohl Map-Keys als auch Werte in der Schleife benötigen.

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

Beachten Sie, dass die For-Each-Schleife in Java 5 eingeführt wurde, sodass diese Methode nur in neueren Versionen der Sprache funktioniert. Es wird auch eine For-Each-Schleife ausgelöstNullPointerException Wenn Sie versuchen, über eine Map zu iterieren, die null ist, sollten Sie vor dem Iterieren immer prüfen, ob Nullreferenzen vorhanden sind.

Methode # 2: Durchlaufen von Schlüsseln oder Werten mit einer For-Each-Schleife.

Wenn Sie nur Schlüssel oder Werte aus der Map benötigen, können Sie KeySet oder Werte anstelle von EntrySet durchlaufen.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

// Iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}

// Iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}

Diese Methode bietet einen leichten Leistungsvorteil gegenüberentrySet Iteration (ca. 10% schneller) und ist sauberer.

Methode # 3: Iterieren mit Iterator.

Verwenden von Generika:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Ohne Generika:

Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry entry = (Map.Entry) entries.next();
    Integer key = (Integer)entry.getKey();
    Integer value = (Integer)entry.getValue();
    System.out.println("Key = " + key + ", Value = " + value);
}

Sie können dieselbe Technik auch zum Durchlaufen verwendenkeySet oder Werte.

Diese Methode mag redundant aussehen, hat aber ihre eigenen Vorteile. Erstens ist dies die einzige Möglichkeit, in älteren Java-Versionen über eine Karte zu iterieren. Das andere wichtige Feature ist, dass es die einzige Methode ist, mit der Sie Einträge während der Iteration durch Aufrufen aus der Karte entfernen könneniterator.remove(). Wenn Sie versuchen, dies während der For-Each-Iteration zu tun, erhalten Sie "unvorhersehbare Ergebnisse" gemäßJavadoc.

Aus Sicht der Leistung entspricht diese Methode einer For-Each-Iteration.

Methode 4: Durchlaufen von Schlüsseln und Suchen nach Werten (ineffizient).

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}

Dies scheint eine sauberere Alternative für Methode 1 zu sein, ist jedoch in der Praxis ziemlich langsam und ineffizient, da das Abrufen von Werten über einen Schlüssel möglicherweise zeitaufwändig ist (diese Methode ist in verschiedenen Map-Implementierungen 20% -200% langsamer als Methode 1) ). Wenn Sie FindBugs installiert haben, wird dies erkannt und Sie werden vor ineffizienter Iteration gewarnt. Diese Methode sollte vermieden werden.

Fazit:

Wenn Sie nur Schlüssel oder Werte aus der Karte benötigen, verwenden Sie Methode 2. Wenn Sie mit einer älteren Java-Version (weniger als 5) nicht weiterkommen oder Einträge während der Iteration entfernen möchten, müssen Sie Methode 3 verwenden. Verwenden Sie andernfalls Methode 1.

@ohbrobig noch ist es O (1), aber das ist die Laufzeit, so skaliert es. Dies bedeutet nicht, dass der Wert im ersten Zyklus unbedingt abgerufen werden muss. Methode 4 ist definitiv langsamer als Methode 1 user961954
@arvind Wie wäre Methode 4 jemals ineffizient? Per definitionem anrufenget() ist immer O (1) für eine HashMap. Das ist die Definition einer HashMap und der Benutzer hat nach einer HashMap gefragt. Ich verstehe nicht, warum das so hoch gewertet ist. Wenn Sie auf den Link einer anderen Person verweisen, vergewissern Sie sich, dass die gestellte Frage tatsächlich einen Sinn ergibt. ohbrobig
Fügen wir den kleinen Caevet hinzu, der im Falle vonConcurrentMaps, Iteration aufkeySet() stürzt im Allgemeinen ab (es gibt keine Garantie dafür, dass die Werte für zuvor gesammelte Schlüssel vorhanden sind). Die Verwendung von Iteratoren oder Einträgen ist dagegen sicher (sie beziehen sich immer auf vorhandene Objekte). P Marecki
3020

Durchlaufen Sie dieentrySet() wie so:

public static void printMap(Map mp) {
    Iterator it = mp.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry)it.next();
        System.out.println(pair.getKey() + " = " + pair.getValue());
        it.remove(); // avoids a ConcurrentModificationException
    }
}

Lesen Sie mehr überMap.

@ Alex ja ich auch NimChimpsky
@vimukthi was meinst du mit einer lösung dafür? Entfernen Sie einfach dieit.remove(); Linie. Danny
Der vollständige Iteratortyp lautet: import java.util.Iterator; Moebius
Die großen Schritte scheinen also zu sein: 1. Mit entrySet in eine Menge konvertieren 2. In einen Iterator verwandeln und 3. hasNext aufrufen und jedes nächste Objekt in ein Map.Entry-Objekt verwandeln? Jwan622
60

Schlauer:

for (String key : hashMap.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
Dies hängt davon ab, ob Sie die Schlüssel benötigen oder nicht. Wenn nicht, ist es effizienter, entrySet () zu verwenden, da hashCode () nicht aufgerufen wird. icfantv
Java 8-Syntax. Funktioniert möglicherweise immer noch nicht für die Android-Entwicklung. "Android soll nicht zu 100% mit Java SE API-Versionen kompatibel sein, weder mit 6 noch mit 8 noch mit irgendwelchen. ... Die JRE ist die Java-Laufzeitumgebung, während das JDK das Java Development Kit ist. Es ist das JDK, das Sie benötigen für die Entwicklung von Android-Anwendungen zusammen mit dem vorhandenen Android SDK.Dec 9, 2013 "Quelle jasonleonhard
map.get (key) ist für jede Iteration nicht schlauer, sondern langsamer ComputerEngineer88
map.entrySet () gibt Einträge zurück, die bereits sowohl den Schlüssel als auch den Wert enthalten. Auf diese Weise müssen Sie hashCode () nicht aufrufen und den Hash während der Iteration durchsuchen. ComputerEngineer88
43

dass Sie sowohl den Schlüssel als auch den Wert jedes Eintrags benötigen, lesen Sie dieentrySet. Wenn Sie nur die Werte brauchen, dann gibt es dievalues() Methode. Und wenn Sie nur die Schlüssel brauchen, dann verwenden Siekeyset().

Eine schlechte Praxis wäre es, alle Tasten zu durchlaufen und dann innerhalb der Schleife immer zu tunmap.get(key) um den Wert zu bekommen. Wenn Sie das tun, dann ist die erste Option, die ich geschrieben habe, für Sie.

Ein weiterer wichtiger Punkt: Die von keySet () und Collection zurückgegebenen Werte () werden beide von der ursprünglichen Map unterstützt. Das heißt, wenn Sie Änderungen daran vornehmen, werden diese in der Map wiedergegeben. Beide Methoden unterstützen jedoch nicht die Methoden add () und addAll (), dh Sie können dem Set oder dem neuen Wert keinen neuen Schlüssel hinzufügen in der Sammlung. sactiw

Verwandte Fragen