JavaRush /Blog Java /Random-PL /9 najważniejszych pytań na temat mapy w Javie
Treefeed
Poziom 21

9 najważniejszych pytań na temat mapy w Javie

Opublikowano w grupie Random-PL
Przypomnijmy, że mapa to uporządkowane dane składające się z zestawu par klucz-wartość, a każdy klucz może zostać użyty tylko raz na jednej mapie. W tym temacie omówiono 9 podstawowych pytań dotyczących używania Map w Javie i zaimplementowanych w niej klas. Dla uproszczenia w przykładach będę posługiwał się uogólnieniami . Dlatego napiszę po prostu Map, bez podawania specyfikatora Map. Można jednak założyć, że obie wartości K i V są porównywalne, co oznacza, że ​​K rozszerza Porównywalne , a V również rozciąga Porównywalne .9 najważniejszych pytań na temat mapy w Javie - 1

0. Konwersja mapy na listę

W Javie interfejs Map oferuje trzy rodzaje kolekcji: zestaw kluczy, zestaw wartości i zestaw klucz-wartość. Wszystkie z nich można przekształcić w Listę za pomocą konstruktora lub metody addAll(). Poniższy fragment kodu demonstruje, jak utworzyć ArrayList z mapy.
// lista kluczy
List keyList = new ArrayList(Map.keySet());
//lista wartości
List valueList = new ArrayList(Map.valueSet());
//lista klucz-wartość
List entryList = new ArrayList(Map.entrySet());

1. Przejdź przez wszystkie wartości na mapie

Przeglądanie każdej pary klucz-wartość to najbardziej podstawowa procedura przeglądania mapy. W Javie każda para jest przechowywana w polu Map o nazwie Map.Entry . Map.entrySet()zwraca zestaw par klucz-wartość, więc najskuteczniejszym sposobem iteracji przez wszystkie wartości mapy byłoby:
for(Entry entry: Map.entrySet()) {
  //Weź klucz
  K key = entry.getKey();
  //pobierz wartość
  V value = entry.getValue();
}
Możemy również użyć Iterator, szczególnie w wersjach młodszych niż JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
  Entry entry = itr.next();
  //Weź klucz
  K key = entry.getKey();
  //pobierz wartość
  V value = entry.getValue();
}

2. Zamawianie mapy według kluczy

Organizowanie map według klawiszy to kolejna powszechnie stosowana procedura. Pierwszy sposób polega na dodaniu Map.Entry do listy i sortowaniu przy użyciu komparatora sortującego według wartości.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getKey().compareTo(e2.getKey());
  }
});
Inny sposób: użyj SortedMap , która dodatkowo porządkuje także swoje klucze. Jednak wszystkie klucze muszą zawierać Porównywalne lub zostać zaakceptowane przez komparator. Jedną z zaimplementowanych klas SortedMapjest TreeMap . Jego konstruktor akceptuje komparator. Poniższy kod pokazuje, jak zamienić normalny Mapw uporządkowany.
SortedMap sortedMap = new TreeMap(new Comparator() {

  @Override
  public int compare(K k1, K k2) {
    return k1.compareTo(k2);
  }

});
sortedMap.putAll(Map);

3. Zamów mapę według wartości

Dodanie mapy do listy, a następnie jej posortowanie działa w tym przypadku, ale tym razem musisz użyć Entry.getValue(). Poniższy kod jest prawie taki sam jak poprzednio.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getValue().compareTo(e2.getValue());
  }

});
Nadal możemy go użyć SortedMapw tym przypadku, ale tylko wtedy, gdy wartości są unikalne. W takim przypadku możesz zamienić parę klucz-wartość w klucz-wartość. To rozwiązanie ma poważne ograniczenia i nie jest przeze mnie zalecane.

4. Inicjowanie mapy statycznej/niezmiennej

Jeśli chcesz, aby mapa pozostała niezmienna, dobrym sposobem jest skopiowanie jej do niezmiennej mapy. Ta technika programowania defensywnego pomoże Ci stworzyć mapę, która będzie nie tylko bezpieczna w użyciu, ale także bezpieczna dla wątków. Aby zainicjować statyczną/niezmienną mapę, możemy użyć inicjatora static(patrz poniżej). Problem z tym kodem polega na tym, że pomimo zadeklarowania Map jako static final, nadal możemy z nią pracować po inicjalizacji, na przykład Test.Map.put(3,"three");. Więc to nie jest prawdziwa niezmienność. Aby utworzyć niezmienną Mapę przy użyciu statycznego inicjatora, potrzebujemy superanonimowej klasy, którą dodamy do niezmiennej Mapy w ostatnim kroku inicjalizacji. Proszę spojrzeć na drugą część kodu. Kiedy zostanie zgłoszony wyjątek UnsupportedOperationException, jeśli uruchomisz Test.Map.put(3,"three");.
public class Test {

  private static final Map Map;
  static {
    Map = new HashMap();
    Map.put(1, "one");
    Map.put(2, "two");
  }
}
public class Test {

  private static final Map Map;
  static {
    Map aMap = new HashMap();
    aMap.put(1, "one");
    aMap.put(2, "two");
    Map = Collections.unmodifiableMap(aMap);
  }
}
Biblioteka Guava obsługuje również różne sposoby inicjowania kolekcji statycznych i niezmiennych. Aby dowiedzieć się więcej o zaletach narzędzia niezmiennych kolekcji Guava, zobacz sekcję Niezmienne kolekcje w poradniku Guava .

5. Różnica pomiędzy HashMap, TreeMap i Hashtable

Istnieją trzy główne implementacje interfejsu Map w Javie: HashMap , TreeMap i Hashtable . Główne różnice są następujące:
  • Kolejność przejścia . HashMap i HashTable nie gwarantują uporządkowania Mapy; w szczególności nie gwarantują niezmienności kolejności w czasie. Ale TreeMapuporządkuje wszystkie wartości w „naturalnej kolejności” kluczy lub według komparatora.
  • Prawidłowe pary klucz-wartość. HashMappozwala mieć klucz zerowy i wartość zerową. HashTablenie zezwala na klucz zerowy ani wartość zerową. Jeśli TreeMapzostanie użyty porządek naturalny lub komparator nie pozwoli na klucz zerowy, zostanie zgłoszony wyjątek.
  • Synchronizacja . Tylko HashTablezsynchronizowane, reszta nie. Ale „jeśli implementacja bezpieczna dla wątków nie jest potrzebna, zaleca się użycie ” HashMapzamiast tego HashTable.
Bardziej szczegółowe porównanie
.                       | HashMap | HashTable | TreeMap
-------------------------------------------------------

Упорядочивание          |нет      |нет        | да
null в ключ-oznaczający    | да-да   | нет-нет   | нет-да
синхронизировано        | нет     | да        | нет
производительность      | O(1)    | O(1)      | O(log n)
воплощение              | корзины | корзины   | красно-чёрное дерево
Przeczytaj więcej o relacji HashMap vs. Mapa Drzewa vs. Hashtable vs. PołączonaHashMapa .

6. Mapa z wyszukiwaniem/widok wsteczny

Czasami potrzebujemy zestawu par klucz-klucz, co oznacza, że ​​wartości są tak samo unikalne jak klucze (wzór jeden do jednego). Ta spójność pozwala na utworzenie na Mapie „odwróconego widoku/wyszukiwania”. Oznacza to, że możemy znaleźć klucz według jego wartości. Ta struktura danych nazywana jest mapą dwukierunkową i niestety nie jest obsługiwana przez JDK. Zarówno Apache Common Collections, jak i Guava oferują dwukierunkowe implementacje map zwane odpowiednio BidiMap i BiMap. Obydwa wprowadzają ograniczenie, które wymusza mapowanie 1:1 pomiędzy kluczami i wartościami.

7. Płytka kopia mapy

Prawie wszystkie, jeśli nie wszystkie, mapy w Javie zawierają konstruktor kopiujący dla innej mapy. Ale procedura kopiowania nie jest zsynchronizowana. Oznacza to, że gdy jeden wątek kopiuje Mapę, inny wątek może zmienić jej strukturę. Aby zapobiec nagłej desynchronizacji kopii, należy w takim przypadku skorzystać z jednego z nich Collections.synchronizedMap().
Map copiedMap = Collections.synchronizedMap(Map);
Innym interesującym sposobem płytkiego kopiowania jest użycie rozszerzenia clone(). Ale NIE jest to zalecane nawet przez twórcę frameworku kolekcji Java, Joshuę Blocha. W debacie „ Copy Constructor vs. Cloning ” zajmuje stanowisko: Cytat: „Często włączam metodę publicznego klonowania do konkretnych zajęć, ponieważ ludzie oczekują, że ona tam będzie. ...szkoda, że ​​klonowanie jest zepsute, ale to się wydarzyło. ... Klonowanie to słaby punkt i uważam, że należy ostrzec ludzi o jego ograniczeniach. Z tego powodu nawet nie pokazuję, jak używać metody clone()do kopiowania Map

8. Utwórz pustą mapę

Jeśli Mapniezmienne, użyj:
Map = Collections.emptyMap();
Lub użyj dowolnego innego przykładu wykonania. Na przykład:
Map = new HashMap();
KONIEC
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION