Map-Durchlauf in Java: Wie man ohne Schmerz und Geschwindigkeitsverlust iteriert

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum Ihr Code scheinbar grundlos langsamer werden kann?

\n

Stellen Sie sich vor: Sie haben einen perfekten Algorithmus geschrieben, alle Unit-Tests bestanden, aber in der Produktion beginnt die Anwendung plötzlich zu "ruckeln". Meistens liegt es nicht am Algorithmus selbst, sondern daran, wie Sie über Collections iterieren. Dies gilt insbesondere für Java Map – eine Datenstruktur, die in 9 von 10 Unternehmensprojekten vorkommt.

\n

Die Frage "How do I efficiently iterate over each entry in a Java Map?" hat auf Stack Overflow nicht umsonst Zehntausende von Aufrufen. Viele Entwickler, selbst mit 2-3 Jahren Erfahrung, verwenden suboptimale Ansätze. Lassen Sie uns klären, wie man eine Map richtig durchläuft und warum eine Methode bis zu 10-mal schneller sein kann als eine andere.

\n\n

Anatomie einer Java Map: Was steckt drin?

\n

Bevor wir über Iteration sprechen, erinnern wir uns an den Aufbau. HashMap ist eine Hashtabelle mit Buckets. TreeMap ist ein Rot-Schwarz-Baum. LinkedHashMap ist ein Hybrid mit einer doppelt verketteten Liste. Jede dieser Strukturen speichert key-value-Paare, aber die Methoden zu deren Durchlauf unterscheiden sich in Geschwindigkeit und Speicherverbrauch.

\n

Die wichtigsten Ansichtssammlungen (view collections), die eine Map bereitstellt:

\n
    \n
  • keySet() – die Menge der Schlüssel
  • \n
  • values() – die Sammlung der Werte
  • \n
  • entrySet() – die Menge der Paare (Schlüssel-Wert)
  • \n
\n

Durch diese drei "Fenster" werden wir auf die Daten blicken.

\n\n

Methode Nr. 1: Klassischer entrySet mit for-each (am beliebtesten)

\n

Dies ist ein grundlegendes, aber sehr effizientes Muster. Sie erhalten Zugriff auf sowohl Schlüssel als auch Wert in einer einzigen Iteration.

\n
Map<String, Integer> map = new HashMap<>();\n// ... map befüllen\nfor (Map.Entry<String, Integer> entry : map.entrySet()) {\n    String key = entry.getKey();\n    Integer value = entry.getValue();\n    // Ihre Logik\n}
\n

Warum ist das effizient? Weil entrySet() eine View (Ansicht) und keine Kopie der Daten zurückgibt. Der Iterator durchläuft die internen Knoten (Node) der HashMap, und jeder Aufruf von next() liefert sofort sowohl Schlüssel als auch Wert. Es erfolgt keine zusätzliche Hash-Suche.

\n

Wann verwenden: Immer, wenn beide Komponenten eines Paares benötigt werden. Dies ist der De-facto-Standard in der Java-Community.

\n\n

Methode Nr. 2: keySet + get (Anti-Pattern, das Sie vermeiden sollten)

\n

Viele Anfänger schreiben so:

\n
for (String key : map.keySet()) {\n    Integer value = map.get(key);\n    // Logik\n}
\n

Auf den ersten Blick ist der Code lesbar. Aber intern berechnet HashMap.get() jedes Mal den Hash des Schlüssels neu und durchläuft die Kollisionskette. Bei 100 Elementen ist das unbemerkt, aber bei 100.000 führt es bereits zu einer ernsthaften Leistungsverschlechterung. Im schlimmsten Fall (viele Kollisionen) verwandelt sich die Komplexität von O(n) in O(n²).

\n

Fazit: Wenn Sie sowohl Schlüssel als auch Wert benötigen, verwenden Sie entrySet(). Wenn Sie nur Schlüssel benötigen, ist keySet() ideal.

\n\n

Methode Nr. 3: Iterator mit explizitem Entfernen (für Mutationen während des Durchlaufs)

\n

Manchmal müssen Sie Elemente direkt während der Iteration aus einer Map entfernen. Die for-each-Schleife wirft eine ConcurrentModificationException. Hier hilft der Iterator:

\n
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();\nwhile (iterator.hasNext()) {\n    Map.Entry<String, Integer> entry = iterator.next();\n    if (entry.getValue() < 0) {\n        iterator.remove(); // sicheres Entfernen\n    }\n}
\n

Diese Methode ist besonders nützlich, wenn Sie Daten "on the fly" filtern. Der Iterator arbeitet bei HashMap mit O(1) pro Entfernung, da er den aktuellen Knoten kennt.

\n\n

Methode Nr. 4: forEach mit Lambda (Java 8+)

\n

Seit Java 8 hat Map eine eigene forEach-Methode:

\n
map.forEach((key, value) -> {\n    System.out.println(key + " -> " + value);\n});
\n

Unter der Haube

Blogs

Buchempfehlungen