Interfejs Java Map jest częścią środowiska Java Collection, ale nie jest podtypem interfejsu Collection. Zachowuje się więc inaczej niż, powiedzmy, listy lub inne obiekty kolekcji. Każdy element Map<Key, Value> reprezentuje parę klucz-wartość. Zarówno klucz, jak i wartość to niektóre obiekty. Wszystkie klucze na danej mapie są unikalne, a wartości nie, więc można je duplikować. Możesz myśleć o Mapie w Javie jak o czymś w rodzaju słownika lub katalogu sklepu internetowego, w którym możesz znaleźć dowolny artykuł za pomocą jego unikalnego indeksu. Klucz jest unikalnym identyfikatorem wartości w Mapie. Na przykład w Map<String, Item> String jest identyfikatorem jakiegoś przedmiotu ze sklepu internetowego. Zgodnie z dokumentacją Mapa posiada następujące Subinterfejsy:
Wiązania ;
Współbieżna mapa<K,V> ;
ConcurrentNavigableMap<K,V> ;
Kontekst logicznego komunikatu ;
MessageContext ;
Mapa nawigacji<K,V> ;
SOAPMessageContext ;
SortowanaMapa<K,V> .
I implementuje klasy:
StreszczenieMapa
Atrybuty
Dostawca autoryzacji
Współbieżna mapa Hash
Współbieżna mapa listy pominięć
EnumMap
HashMap
Hashtable
Tożsamość HashMap
LinkedHashMap
Powody stanu drukarki
Nieruchomości
Dostawca
Wskazówki dotyczące renderowania
Proste powiązania
Obsługa danych tabelarycznych
Mapa drzewa
UIDefaults
Słaba mapa haszowania
Java AbstractMap to klasa abstrakcyjna, która implementuje większość interfejsu Map.
Java HashMap to struktura danych służąca do przechowywania par klucz-wartość przy użyciu tabeli skrótów.
Java TreeMap to struktura danych wykorzystująca drzewo, czyli wyświetlanie z posortowanymi kluczami.
WeakHashMap, aby użyć tablicy skrótów ze słabymi kluczami, wyświetlić wartości, które mogą zostać usunięte przez moduł wyrzucania elementów bezużytecznych, jeśli nie są już używane.
LinkedHashMap to mapa z kolejnością dodawania elementów, umożliwia iterację w kolejności wstawiania.
EnumMap rozszerza klasę AbstractMap do użytku z kluczami enum.
IdentityHashMap wykorzystuje sprawdzanie równoważności referencyjnej podczas porównywania dokumentów, mapowanie z kluczami porównywanymi za pomocą operacji
== zamiast metody
equals()
Tutaj interesują nas najpopularniejsze implementacje interfejsu mapy: HashMap, TreeMap i LinkedHashMap. Nawiasem mówiąc, kolejność elementów mapy zależy od konkretnych implementacji. Powiedzmy, że TreeMap i LinkedHashMap mają przewidywalną kolejność elementów, podczas gdy HashMap nie.
Metody mapowania
Główne operacje dowolnej mapy to wstawianie, usuwanie i wyszukiwanie elementów.
public Object put(Object key, Object value) wstawia element do mapy.
public void putAll(Map map) wstawia określoną mapę wewnątrz mapy.
public Object remove(Object key) usuwa wpis zgodnie z podanym kluczem.
public Object get(Object key) zwraca wartość dla określonego klucza.
public boolean zawieraKey(Object key) wyszukuje określony klucz z tej mapy
public Set keySet() zwraca widok Set zawierający wszystkie klucze
public Set entrySet() zwraca widok zestawu ze wszystkimi kluczami i wartościami.
Co to jest HashMap
Co to jest HashMap? Jest to najpopularniejsza implementacja interfejsu Map<Key,Value>. Ta struktura danych jest oparta na zasadzie mieszania.
Główna zasada działania HashMap: haszowanie
Aby zrozumieć, czym jest hashmap i jak działa, porozmawiajmy najpierw o hashowaniu i funkcjach haszujących. Funkcja skrótu jest tylko funkcją w sensie matematycznym. Jest więc pewna wartość wejściowa (obiekt, fragment danych) i funkcja konwertuje ją za pomocą odpowiedniej reguły na wartość wyjściową - hash. Dość często hash jest liczbą szesnastkową o odpowiedniej długości. Zasady procesów konwersji mogą być różne, ale podlegają następującym zasadom:
Określone wejście (obiekt) ma określony kod skrótu.
Jeśli dwa obiekty są równe, ich kody skrótu również są równe. Odwrotność nie jest prawdą.
Jeśli kody skrótu są różne, obiekty zdecydowanie nie są równe.
Czasami różne obiekty mogą mieć ten sam kod skrótu. Jest to bardzo mało prawdopodobne zdarzenie, zwane „kolizją”, a dobrej jakości funkcja haszująca powinna zminimalizować prawdopodobieństwo kolizji.
W Javie każdy obiekt ma swój kod skrótu. Jest obliczany za pomocą metody hashCode klasy Object, klasy nadrzędnej wszystkich obiektów Java. Zwykle programiści nadpisują tę metodę dla swoich własnych klas, a także metody z nią związane.
HashMap: jak to działa
Więc klasa HashMap<K,V> jak każda implementacja Map składa się z kluczy i wartości. Przechowuje klucze przy użyciu zasad haszowania. Wewnątrz HashMap pary klucz-wartość są przechowywane w „wiadrach”, te zasobniki razem tworzą „tabelę”, wewnętrzną tablicę połączonych list, a jej początkowy rozmiar to 16. HashMap w Javie używa kodu skrótu klucza do określenia segmentu, w którym powinna być mapowana para klucz/wartość: Trudną cechą HashMap jest to, że każda komórka (wiaderko) tabeli [] przechowuje nie tylko jedną parę, ale kilka. Nie są one przechowywane jako jawny obiekt (jak LinkedList), ale jako niejawny łańcuch. Łańcuch powstaje dzięki temu, że każda para przechowuje link do następnej pary. Oznacza to, że wszystkie pary HashMap są rozproszone w 16 łańcuchach. Kiedy umieszczasz nową parę w tabeli, brany jest pod uwagę skrót klucza. Ten skrót nie jest funkcją hashcode wbudowaną w obiekt klucza. Uważa się, że mieści się w przedziale 0-15. Para jest dodawana do łańcucha par przechowywanych w zasobniku z indeksem mieszania. Takie podejście daje nam przyspieszenie wyszukiwania. Szukając pary po kluczu, nie ma potrzeby przeglądania całej tabeli. Hash klucza jest brany pod uwagę i sprawdzany jest tylko łańcuch, który jest przechowywany w komórce z indeksem hash. Jeśli w HashMap jest zbyt wiele par, łańcuchy stają się zbyt długie. Następnie zwiększa się rozmiar tablicy, przeliczany jest hash wszystkich przechowywanych obiektów i są one rozrzucane wzdłuż nowych łańcuchów.
Deklaracja HashMap
Jeśli przejdziesz do kodu klasy HashMap, znajdziesz następną deklarację:
Gdzie K to typ kluczy obsługiwanych przez tę mapę, a V to typ mapowanych wartości. To jest przykład deklaracji HashMap z kluczem Integer i wartością String w twoim kodzie:
Object get(Object key) zwraca wartość dla określonego klucza;
Object put(Key k, Value v) wstawia mapowanie wartości klucza do mapy;
Object remove(Object key) usuwa mapowanie dla określonego klucza z tej mapy, jeśli istnieje;
void clear() usuwa wszystkie pary klucz-wartość z mapy HashMap;
Object clone() zwraca płytką kopię tej instancji HashMap bez klonowania kluczy i wartości;
boolean zawieraKey(Object key) zwraca true, jeśli określony klucz jest znaleziony na mapie, false, jeśli nie;
boolean zawieraValue(Object Value) zwraca true, jeśli określony klucz jest znaleziony na mapie, false, jeśli nie;
boolean isEmpty() zwraca true, jeśli mapa jest pusta, false, jeśli nie jest;
Set keySet() zwraca zestaw kluczy pobranych z mapy;
int size() zwraca ilość odwzorowań klucz-wartość;
Collection values() zwraca kolekcję wartości mapy;
Object remove(Object key) usuwa parę klucz-wartość dla określonego klucza;
void putAll(Map m) kopiuje wszystkie elementy mapy na inną mapę.
Przykład Java HashMap
Stwórzmy program z Java HashMap Example, aby zademonstrować, jak to działa:
importjava.util.HashMap;importjava.util.Map;importjava.util.Iterator;importjava.util.Set;publicclassHashMap{publicstaticvoidmain(String[] args){{// HashMap declarationHashMap<Integer,String> myHashMap =newHashMap<Integer,String>();//Adding elements into HashMap
myHashMap.put(7,"Johnny");
myHashMap.put(8,"Ivy");
myHashMap.put(1,"Rick");
myHashMap.put(4,"Stan");
myHashMap.put(3,"Kyle");//print out the map content using IteratorSet set = myHashMap.entrySet();Iterator iterator = set.iterator();while(iterator.hasNext()){Map.Entry mapEntry =(Map.Entry) iterator.next();System.out.print("key: "+ mapEntry.getKey()+" value: ");System.out.println(mapEntry.getValue());}System.out.println("get an element from myHashMap via key and print the value out:");System.out.println(myHashMap.get(8));//print out hashMap on standard way:System.out.println(myHashMap);// Get values based on keyStringvar= myHashMap.get(2);//here we'll get null, we don't have such a keySystem.out.println("Value with key 2: "+var);var= myHashMap.get(7);System.out.println("Value with key 7: "+var);// Remove values based on key
myHashMap.remove(4);System.out.println("myHashMap after removing element:");System.out.println(myHashMap);
myHashMap.clear();System.out.println("myHashMap after total clearing:");System.out.println(myHashMap);}}}
Wynik działania programu:
key: 1 value: Rick
key: 3 value: Kyle
key: 4 value: Stan
key: 7 value: Johnny
key: 8 value: Ivy
get an element from myHashMap via key and print the value out:
Ivy
{1=Rick, 3=Kyle, 4=Stan, 7=Johnny, 8=Ivy}
Value with key 2: null
Value with key 7: Johnny
myHashMap after removing element:
{1=Rick, 3=Kyle, 7=Johnny, 8=Ivy}
myHashMap after total clearing:
{}
Mapa drzewa
TreeMap w Javie również implementuje interfejs Map<Key,Value>, ale jest oparty na strukturze danych drzewa Red-Black. Drzewo składa się z „węzłów” i linii łączących węzły – gałęzie. Węzeł „główny” znajduje się na szczycie drzewa. Od korzenia mogą być gałęzie i węzły. Jest to struktura hierarchiczna, o której możesz pomyśleć te węzły jako „dzieci" korzenia. Węzeł potomny może mieć swoje własne dzieci - węzły niższe. Węzły bez dzieci nazywane są „węzłami końcowymi" lub „liśćmi". Drzewo binarne to drzewo, w którym każdy węzeł ma zero, jeden , lub dwoje dzieci.Drzewo wyszukiwania binarnego jest strukturą, w której każdy wewnętrzny węzeł przechowuje klucz, a czasem powiązaną wartość, i ma dwa wyróżnione poddrzewa („lewe” i „prawe”). Samobalansujące się drzewo wyszukiwania binarnego to oparte na węzłach drzewo wyszukiwania binarnego, które automatycznie utrzymuje małą wysokość (maksymalną liczbę poziomów poniżej korzenia) w obliczu dowolnych wstawień i usunięć elementów. Drzewo czerwono-czarne jest zrównoważonym drzewem binarnym o właściwościach:
Każdy węzeł jest czerwony lub czarny
Korzeń jest zawsze czarny
Każdy liść jest węzłem NIL (rodzaj pustego, zerowego) i jest czarny
Jeśli węzeł jest czerwony, jego dzieci są zdecydowanie czarne.
Każda prosta ścieżka od węzła do liścia potomnego zawiera taką samą liczbę czarnych węzłów.
Funkcje TreeMap
TreeMap wykorzystuje drzewiastą strukturę danych do przechowywania kluczy jako węzłów i sortuje klucze przy użyciu algorytmu Red-Black Tree. Tak więc TreeMap przechowuje swoje wpisy posortowane zgodnie z naturalnym uporządkowaniem kluczy. Dla liczb naturalny jest porządek rosnący, dla łańcuchów — porządek alfabetyczny. Możesz użyć komparatora, jeśli chcesz zmienić logikę zamawiania. Dużą zaletą TreeMap jest sortowanie obiektów w naturalny sposób, podobnie jak znajdowanie niektórych obiektów przy użyciu różnych filtrów i warunków.
Metody TreeMap
Object get(Object key) zwraca wartość odpowiedniego klucza;
Object put(Object key, Object value) wstawia mapowanie do mapy;
Object remove(Object key) usuwa mapowanie dla tego klucza, jeśli zawiera go TreeMap;
boolean zawieraKey(Object key) zwraca true, jeśli ta mapa zawiera mapowanie dla określonego klucza;
boolean zawieraValue(Object value) zwraca wartość true, jeśli TreeMap odwzorowuje jeden lub więcej kluczy na określoną wartość;
Obiekt firstKey() zwraca pierwszy klucz znajdujący się aktualnie na posortowanej mapie;
Obiekt lastKey() zwraca ostatni klucz znajdujący się aktualnie na posortowanej mapie;
void putAll(Map map) kopiuje wszystkie mapowania z określonej mapy na mapę;
Set entrySet() zwraca ustawiony widok mapowań
int size() zwraca liczbę odwzorowań klucz-wartość
Collection values() zwraca widok kolekcji wartości
Object clone() zwraca płytką kopię TreeMap
void clear() usuwa wszystkie mapowania z TreeMap
SortedMap headMap(Object wartość_klucza) zwraca widok części mapy mniejszej niż wartość parametru wartość_klucza
Set keySet() zwraca widok zestawu kluczy zawartych w mapie drzewa
SortedMap subMap(K fromKey, K toKey) zwraca widok części tej mapy, której klucze mają zakres od fromKey, włącznie, do toKey, wyłączne
Obiekt firstKey() zwraca pierwszy klucz z TreeMap.
Przykład TreeMap
importjava.util.TreeMap;importjava.util.Set;importjava.util.Iterator;importjava.util.Map;publicclassTreeMapExample{publicstaticvoidmain(String args[]){//TreeMap declarationTreeMap<Integer,String> myTreeMap =newTreeMap<Integer,String>();//put elements to TreeMap
myTreeMap.put(1,"Stuart");
myTreeMap.put(23,"Michael");
myTreeMap.put(7,"Johnny");
myTreeMap.put(5,"Ivy");
myTreeMap.put(2,"Alex");//Display and print out myTreeMap using IteratorSet set = myTreeMap.entrySet();Iterator iterator = set.iterator();while(iterator.hasNext()){Map.Entry myEntry =(Map.Entry) iterator.next();System.out.print("key: "+ myEntry.getKey()+" value: ");System.out.println(myEntry.getValue());}//TreeMap printed in classical waySystem.out.println(myTreeMap);//removing an element with the key =2
myTreeMap.remove(2);//myTreeMap after removing:System.out.println(myTreeMap);}}
Wynik działania programu:
key: 1 value: Stuart
key: 2 value: Alex
key: 5 value: Ivy
key: 7 value: Johnny
key: 23 value: Michael
{1=Stuart, 2=Alex, 5=Ivy, 7=Johnny, 23=Michael}
{1=Stuart, 5=Ivy, 7=Johnny, 23=Michael}
LinkedHashMap
LinkedHashMap to struktura danych, która łączy połączone listy i mapy skrótów. Rzeczywiście, LinkedHashMap rozszerza klasę HashMap i implementuje interfejs Map, ale o co chodzi z połączonymi listami? Deklaracja LinkedHashMap:
Ta nowa linkedHashMap dziedziczy właściwości z HashMap (takie jak tabela, współczynnik obciążenia, próg, rozmiar, zestaw wpisów), a także otrzymuje dwie specjalne właściwości:
header to głowa listy podwójnie połączonej. Podczas inicjalizacji wskazuje się
accessOrder wskazuje, jak uzyskać dostęp do elementów za pomocą iteratora. Jeśli to prawda, w kolejności ostatniego dostępu. Jeśli false, dostęp będzie w kolejności, w jakiej elementy zostały wstawione.
Ta połączona lista definiuje kolejność iteracji. Zwykle jest to kolejność wstawiania kluczy do mapy.
Metody LinkedHashMap
Object get(Object key) zwraca wartość, na którą odwzorowany jest określony klucz, lub null, jeśli ta mapa nie zawiera mapowania dla klucza
void clear() usuwa wszystkie mapowania z mapy.
boolean zawieraKey(Object key) zwraca wartość true, jeśli określony element jest odwzorowany przez jeden lub więcej kluczy
boolean removeEldestEntry(Map.Entry najstarszy) zwraca wartość true, jeśli mapa usunie swój najstarszy wpis z mapy
Set<Map.Entry<K,V>> entrySet() zwraca widok zestawu odwzorowań zawartych na tej mapie
void forEach(BiConsumer<?super K,?superV>action) wykonuje daną akcję dla każdego wpisu w tej mapie, dopóki wszystkie wpisy nie zostaną przetworzone lub akcja nie zgłosi wyjątku.
Obiekt getOrDefault(Object key, V defaultValue) zwraca wartość, na którą odwzorowany jest określony klucz. Jeśli mapa nie zawiera mapowania dla klucza, zwraca wartość domyślną.
Funkcja Set<K> keySet() zwraca widok zestawu kluczy zawartych w mapie
boolean removeEldestEntry(Map.Entry<K,V> najstarszy) zwraca wartość true, jeśli ta mapa powinna usunąć swój najstarszy wpis
void replaceAll(BiFunction<?super K,?super V,?extenses V> function) zastępuje każdą wartość wpisu wynikiem wywołania danej funkcji na tym wpisie, dopóki wszystkie wpisy nie zostaną przetworzone lub funkcja zgłosi wyjątek.
Collection<v>values() zwraca widok kolekcji wartości zawartych na mapie
Przykład LinkedHashMap
importjava.util.LinkedHashMap;importjava.util.Set;importjava.util.Iterator;importjava.util.Map;publicclassHashLinkedListExample{publicstaticvoidmain(String args[]){// LinkedHashMap DeclarationLinkedHashMap<Integer,String> myLinkedHashMap =newLinkedHashMap<Integer,String>();//Adding elements into LinkedHashMap
myLinkedHashMap.put(7,"Johnny");
myLinkedHashMap.put(12,"Rick");
myLinkedHashMap.put(1,"Kyle");
myLinkedHashMap.put(5,"Percy");
myLinkedHashMap.put(85,"Sebastian");// Generate a Set of entriesSet set = myLinkedHashMap.entrySet();// Display and print out the nodes of LinkedHashMapIterator iterator = set.iterator();while(iterator.hasNext()){Map.Entry me =(Map.Entry)iterator.next();System.out.print("key: "+ me.getKey()+" value: "+me.getValue()+"\n");}//print out HashLinkedMap on standard way:System.out.println(myLinkedHashMap);
myLinkedHashMap.put(21,"Ivy");System.out.println(myLinkedHashMap);
myLinkedHashMap.remove(12);System.out.println(myLinkedHashMap);
myLinkedHashMap.put(12,"Ronny");System.out.println(myLinkedHashMap);
myLinkedHashMap.put(1,"Stan");System.out.println(myLinkedHashMap);}}
Tutaj tworzymy nową LinkedHashMap, dodając pięć elementów, a następnie drukujemy ją za pomocą iteratora iw klasyczny sposób. Jak widać, LinkedHashMap utrzymuje kolejność wstawiania. Po nim usuwamy element z naszej Mapy, potem dodajemy nowy i później jeszcze jeden element z kluczem, który już jest na mapie. Zastępuje starą wartość zmapowaną do tego klucza. Wynik uruchomionego programu:
HashMap, TreeMap i LinkedHashMap to implementacje interfejsów Map. HashMap i LinkedHashMap to struktury danych, które mieszają klucze. TreeMap wykorzystuje naturalną kolejność swoich kluczy do organizowania drzewa wyszukiwania. Zamówienie:
HashMap nie zachowuje żadnego porządku.
TreeMap sortuje wpisy w rosnącej kolejności kluczy.
LinkedHashMap utrzymuje kolejność wstawiania.
Klucze zerowe:
HashMap i LinkedHashMap pozwalają na posiadanie jednego klucza zerowego.
LinkedHashMap nie zezwala na klucze zerowe w przypadku, gdy klucze używają naturalnego porządku lub Komparator nie obsługuje porównania na polach zerowych.
Spójrzmy na przykład mapy Java, który zawiera wszystkie trzy implementacje omówione w tym artykule:
Jak widać kolejność elementów w HashMap nie jest oczywista, w treeMap zależy od kluczy, w LinkedHashMap chodzi o kolejność wstawiania. Jeśli spróbujemy umieścić klucz zerowy w linkedHashMap, otrzymamy wyjątek NullPointerException, ale w linkedHashMap1, gdzie klucze to String, możemy to zrobić. Mapa skrótów to najlepsza implementacja mapy ogólnego przeznaczenia. Zapewnia maksymalną szybkość wyszukiwania, szybkie operacje przechowywania i pobierania, ale należy pamiętać o jego chaotycznym uporządkowaniu. Połączona mapa skrótów dziedziczy zalety HashMap i otrzymuje zamówienie na klucze. Zawiera jednak linkedList, który jest stosunkowo kosztowny pod względem pamięci. jest wolniejszy niż HashMap w wyszukiwaniu i nieco wolniejszy w dodawaniu/usuwaniu z powodu utrzymywania połączonej listy. Mapa drzewa przechowuje klucze posortowane w porządku rosnącym. Jednakże, Aby utrwalić to, czego się nauczyłeś, zalecamy obejrzenie lekcji wideo z naszego kursu języka Java
Java Developer w Toshiba Global Commerce Solutions
Before IT, Alexandr managed to work in various fields and companies: at Guinness World Records, London Olympics 2021, and Nielsen, ... [Przeczytaj pełną biografię]