JavaRush /Java-Blog /Random-DE /Antworten auf die häufigsten Fragen zur Kartenoberfläche

Antworten auf die häufigsten Fragen zur Kartenoberfläche

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute geben wir Antworten auf die häufigsten Fragen zu Map, aber erinnern wir uns zunächst daran, was es ist. Antworten auf die häufigsten Fragen zur Kartenoberfläche – 1Eine Karte ist eine Datenstruktur, die eine Reihe von Schlüssel-Wert-Paaren enthält. Seine Datenstruktur ähnelt einem Wörterbuch, weshalb es oft so genannt wird. Gleichzeitig ist Map eine Schnittstelle und enthält im Standard-JDK die Hauptimplementierungen: Hashmap, LinkedHashMap, Hashtable, TreeMap. Die am häufigsten verwendete Implementierung ist Hashmap, daher werden wir sie in unseren Beispielen verwenden. So sieht das Standarderstellen und Füllen einer Karte aus:
Map<Integer, String> map = new HashMap<>();
map.put(1, "string 1");
map.put(2, "string 2");
map.put(3, "string 3");
Und so erhalten Sie Werte per Schlüssel:
String string1 = map.get(1);
String string2 = map.get(2);
String string3 = map.get(3);
Wenn alle oben genannten Punkte klar sind, fahren wir mit unseren Antworten auf häufig gestellte Fragen fort!

0. So durchlaufen Sie alle Kartenwerte

Das Iterieren über Werte ist die häufigste Operation, die Sie mit Karten durchführen. Alle Schlüssel-Wert-Paare werden in der internen Map.Entry-Schnittstelle gespeichert. Um sie abzurufen, müssen Sie die aufrufen entrySet(). Es gibt eine Menge von Paaren zurück, die durchgeschleift werden können:
for(Map.Entry<Integer, String> entry: map.entrySet()) {
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

Или используя итератор:
Iterator<Map.Entry<Integer, String>> itr = map.entrySet().iterator();
while(itr.hasNext()) {
   Map.Entry<Integer, String> entry =  itr.next();
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

1. So konvertieren Sie eine Karte in eine Liste

Die Map-Schnittstelle verfügt über drei Methoden, die eine Liste von Elementen zurückgeben:
  • keySet() – gibt einen Satz Schlüssel zurück;
  • Werte() – gibt eine Sammlung von Werten zurück;
  • enterSet() – gibt einen Satz von Schlüsselwertsätzen zurück.
Wenn Sie sich die Konstruktoren der Klasse ansehen ArrayList, werden Sie feststellen, dass es einen Konstruktor mit einem Argument vom Typ Collection gibt. Da Set ein Nachkomme von Collection ist, können die Ergebnisse aller oben genannten Methoden an den Konstruktor der Klasse übergeben werden ArrayList. Also erstellen wir neue Listen und füllen sie mit Werten aus Map:
// key list
List<Integer> keyList = new ArrayList<>(map.keySet());
// value list
List<String> valueList = new ArrayList<>(map.values());
// key-value list
List<Map.Entry<Integer, String>> entryList = new ArrayList<>(map.entrySet());

2. So sortieren Sie Kartenschlüssel

Auch das Sortieren von Karten ist ein recht häufiger Vorgang in der Programmierung. Sie können dies auf verschiedene Arten tun:
  1. Fügen Sie Map.Entry in eine Liste ein und sortieren Sie sie mit Comparator .

    Im Komparator vergleichen wir nur die Schlüsselpaare:

    List> list = new ArrayList(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
       @Override
       public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
           return o1.getKey() - o2.getKey();
       }
    });
    

    Wenn Sie Lambdas verstehen, kann dieser Eintrag deutlich gekürzt werden:

    Collections.sort(list, Comparator.comparingInt(Map.Entry::getKey));
  2. Verwenden Sie SortedMap, oder genauer gesagt, seine Implementierung TreeMap, die einen Comparator in ihrem Konstruktor benötigt. Dieser Komparator wird auf die Map-Schlüssel angewendet, daher müssen die Schlüssel Klassen sein, die die Schnittstelle implementieren Comparable:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(new Comparator<Integer>() {
       @Override
       public int compare(Integer o1, Integer o2) {
           return o1 - o2;
       }
    });

    Und natürlich kann alles mit Lambdas umgeschrieben werden:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(Comparator.comparingInt(o -> o));

    Im Gegensatz zur ersten Methode speichern wir mit SortedMap die Daten immer in sortierter Form.

3. So sortieren Sie Kartenwerte

Hier sollten Sie einen ähnlichen Ansatz wie beim ersten für Schlüssel verwenden: Holen Sie sich eine Liste mit Werten und sortieren Sie sie in der Liste:
List <Map.Entry<Integer, String>> valuesList = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
   @Override
   public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
       return o1.getValue().compareTo(o2.getValue());
   }
});
Und das Lambda dafür sieht so aus:
Collections.sort(list, Comparator.comparing(Map.Entry::getValue));

4. Was ist der Unterschied zwischen HashMap, TreeMap und Hashtable?

Wie bereits erwähnt, gibt es drei Hauptimplementierungen der Map-Schnittstelle. Jeder von ihnen hat seine eigenen Eigenschaften:
  1. Reihenfolge der Elemente. HashMapund Hashtablegarantieren nicht, dass die Artikel in der Reihenfolge gespeichert werden, in der sie hinzugefügt wurden. Darüber hinaus garantieren sie nicht, dass sich die Reihenfolge der Elemente im Laufe der Zeit nicht ändert. Dies wiederum TreeMapgarantiert die Speicherung der Elemente in der Reihenfolge, in der sie hinzugefügt wurden, oder gemäß einem bestimmten Komparator.

  2. Gültige Werte. HashMapermöglicht es Ihnen, einen Schlüssel und einen Nullwert zu haben, HashTablenein. TreeMap kann Nullwerte nur verwenden, wenn der Komparator dies zulässt. Ohne Verwendung eines Komparators (durch Speichern von Paaren in der Reihenfolge, in der sie hinzugefügt wurden) ist Null nicht zulässig.

  3. Synchronisation. Nur HashTablesynchronisiert, der Rest nicht. Wenn nicht von verschiedenen Threads auf die Karte zugegriffen wird, wird empfohlen, HashMap anstelle von HashTable zu verwenden.

Und ein allgemeiner Vergleich der Implementierungen:
HashMap Hash-tabelle TreeMap
Reihenfolge der Elemente Nein Nein Ja
null als Wert Ja Nein Ja Nein
Thread-Sicherheit Nein Ja Nein
Algorithmische Komplexität der Suche nach Elementen O(1) O(1) O(log n)
Datenstruktur unter der Haube Hash-tabelle Hash-tabelle rot-schwarzer Baum

5. So erstellen Sie eine bidirektionale Karte

Manchmal ist es notwendig, eine Datenstruktur zu verwenden, in der sowohl Schlüssel als auch Werte eindeutig sind, das heißt, die Karte enthält Schlüssel-Schlüssel-Paare. Mit dieser Datenstruktur können Sie eine „invertierte Ansicht/Suche“ auf der Karte erstellen. Das heißt, wir können einen Schlüssel anhand seines Werts finden. Diese Datenstruktur wird als bidirektionale Karte bezeichnet, die vom JDK leider nicht unterstützt wird. Aber glücklicherweise ist seine Implementierung in den Apache Common Collections oder Guava-Bibliotheken zu finden. Dort heißt es BidiMap bzw. BiMap. Diese Implementierungen erlegen Einschränkungen hinsichtlich der Eindeutigkeit von Schlüsseln und Werten auf. Dadurch entsteht eine Eins-zu-Eins-Beziehung.

6. So erstellen Sie eine leere Karte

Es gibt zwei Möglichkeiten, eine leere Karte zu erstellen:
  1. Normale Objektinitialisierung:

    Map<Integer, String> emptyMap = new HashMap<>();
  2. Erstellen einer unveränderlichen leeren Karte:

    Map<Integer, String> emptyMap =  Collections.emptyMap();
Wenn wir versuchen, Daten zu einer solchen Karte hinzuzufügen, erhalten wir: UnsupportedOperationExceptionAusnahme. In diesem Artikel haben wir uns die häufigsten Fragen angesehen, die Sie bei der Verwendung der Kartenoberfläche haben könnten.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION