JavaRush /Blog Java /Random-PL /Odpowiedzi na najpopularniejsze pytania dotyczące interfe...

Odpowiedzi na najpopularniejsze pytania dotyczące interfejsu Mapy

Opublikowano w grupie Random-PL
Cześć! Dzisiaj odpowiemy na najczęściej zadawane pytania dotyczące Mapy, ale najpierw przypomnijmy sobie, co to jest. Odpowiedzi na najpopularniejsze pytania dotyczące interfejsu Mapy - 1Mapa to struktura danych zawierająca zestaw par klucz-wartość. Jego struktura danych przypomina słownik i dlatego często jest tak nazywana. Jednocześnie Map jest interfejsem i w standardowym jdk zawiera główne implementacje: Hashmap, LinkedHashMap, Hashtable, TreeMap. Najczęściej stosowaną implementacją jest Hashmap, dlatego będziemy jej używać w naszych przykładach. Tak wygląda standardowe tworzenie i wypełnianie mapy:
Map<Integer, String> map = new HashMap<>();
map.put(1, "string 1");
map.put(2, "string 2");
map.put(3, "string 3");
A oto jak uzyskać wartości według klucza:
String string1 = map.get(1);
String string2 = map.get(2);
String string3 = map.get(3);
Jeśli wszystko powyższe jest jasne, przejdźmy do naszych odpowiedzi na popularne pytania!

0. Jak iterować po wszystkich wartościach mapy

Iteracja po wartościach to najczęstsza operacja wykonywana na mapach. Wszystkie pary klucz-wartość przechowywane są w wewnętrznym interfejsie Map.Entry i aby je uzyskać należy wywołać funkcję entrySet(). Zwraca zestaw par, które można zapętlić:
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. Jak przekonwertować mapę na listę

Interfejs Map posiada 3 metody zwracające listę elementów:
  • keySet() - zwraca zestaw kluczy;
  • wartości() - zwraca kolekcję wartości;
  • EntrySet() - zwraca zestaw zestawów klucz-wartość.
Jeśli spojrzysz na konstruktory klasy ArrayList, zauważysz, że istnieje konstruktor z argumentem typu Collection. Ponieważ Set jest potomkiem Collection, wyniki wszystkich powyższych metod można przekazać do konstruktora klasy ArrayList. Stworzymy więc nowe listy i wypełnimy je wartościami z 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. Jak sortować klucze mapy

Sortowanie map jest również dość powszechną operacją w programowaniu. Możesz to zrobić na kilka sposobów:
  1. Umieść Map.Entry na liście i posortuj ją za pomocą Comparatora .

    W komparatorze będziemy porównywać tylko klucze par:

    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();
       }
    });
    

    Jeśli rozumiesz lambdy, ten wpis można znacznie skrócić:

    Collections.sort(list, Comparator.comparingInt(Map.Entry::getKey));
  2. Użyj SortedMap, a dokładniej jego implementację TreeMap, która w swoim konstruktorze przyjmuje Comparator. Ten komparator zostanie zastosowany do kluczy mapy, więc klucze muszą być klasami implementującymi interfejs Comparable:

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

    I oczywiście wszystko można przepisać za pomocą lambd:

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

    W przeciwieństwie do pierwszej metody, korzystając z SortedMap, dane zawsze będziemy przechowywać w formie posortowanej.

3. Jak sortować wartości mapy

Tutaj należy zastosować podejście podobne do pierwszego dla kluczy - uzyskaj listę wartości i posortuj je na liście:
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());
   }
});
A lambda tego wygląda następująco:
Collections.sort(list, Comparator.comparing(Map.Entry::getValue));

4. Jaka jest różnica pomiędzy HashMap, TreeMap i Hashtable

Jak wspomniano wcześniej, istnieją 3 główne implementacje interfejsu Map. Każdy z nich ma swoją własną charakterystykę:
  1. Kolejność elementów. HashMapi Hashtablenie gwarantujemy, że elementy będą przechowywane w kolejności, w jakiej zostały dodane. Ponadto nie dają gwarancji, że kolejność elementów nie ulegnie zmianie w czasie. Gwarantuje to z kolei TreeMapprzechowywanie elementów w kolejności ich dodawania lub zgodnie z danym komparatorem.

  2. Prawidłowe wartości. HashMappozwala mieć klucz i wartość null, HashTablenie. TreeMap może używać wartości null tylko jeśli komparator na to pozwala. Bez użycia komparatora (poprzez przechowywanie par w kolejności, w jakiej zostały dodane), wartość null jest niedozwolona.

  3. Synchronizacja. Tylko HashTablezsynchronizowane, reszta nie. Jeśli dostęp do mapy nie będzie możliwy dla różnych wątków, zaleca się użycie HashMap zamiast HashTable.

Oraz ogólne porównanie realizacji:
HashMapa HashTable Mapa Drzewa
Kolejność elementów NIE NIE Tak
null jako wartość Tak NIE Nie bardzo
Bezpieczeństwo nici NIE Tak NIE
Złożoność algorytmiczna wyszukiwania elementów O(1) O(1) O(log n)
Struktura danych pod maską tablica mieszająca tablica mieszająca czerwono-czarne drzewo

5. Jak stworzyć mapę dwukierunkową

Czasami konieczne staje się zastosowanie struktury danych, w której zarówno klucze, jak i wartości będą unikalne, czyli mapa będzie zawierać pary klucz-klucz. Ta struktura danych umożliwia utworzenie na mapie „odwróconego widoku/wyszukiwania”. Oznacza to, że klucz możemy znaleźć po jego wartości.Ta struktura danych nazywa się mapą dwukierunkową, która niestety nie jest obsługiwana przez JDK. Ale na szczęście jego implementację można znaleźć w bibliotekach Apache Common Collections lub Guava. Tam nazywa się to odpowiednio BidiMap i BiMap. Implementacje te nakładają ograniczenia na unikalność kluczy i wartości. Tworzy to relację jeden do jednego.

6. Jak stworzyć pustą mapę

Istnieją dwa sposoby utworzenia pustej mapy:
  1. Normalna inicjalizacja obiektu:

    Map<Integer, String> emptyMap = new HashMap<>();
  2. Tworzenie niezmiennej pustej mapy:

    Map<Integer, String> emptyMap =  Collections.emptyMap();
Gdy spróbujemy dodać dane do takiej mapy otrzymamy: UnsupportedOperationExceptionwyjątek. W tym artykule przyjrzeliśmy się najczęstszym pytaniom, jakie możesz mieć podczas korzystania z interfejsu Mapy.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION