Cześć! Dzisiaj porozmawiamy o innej strukturze danych - Mapie. Jego oficjalna rosyjska nazwa to „tablica asocjacyjna”, ale nie jest często używana. Bardziej powszechne opcje to „słownik”, „mapa” lub (najczęściej) slangowy anglicyzm „mapa” :) Wewnątrz Map dane przechowywane są w formacie „klucz” - „wartość”, czyli parami. Zarówno klucze, jak i wartości mogą być dowolnymi obiektami — liczbami, ciągami znaków lub obiektami innych klas.
Czym Map różni się od innych struktur danych
Wcześniej przyglądaliśmy się strukturom danych, w których elementy są przechowywane samodzielnie. W tablicy lub ArrayList / LinkedList przechowujemy określoną liczbę elementów. A co jeśli nasze zadanie trochę się zmieni? Wyobraźmy sobie na przykład, że mamy do czynienia z zadaniem stworzenia listy 100 osób, na której będzie zapisane imię i nazwisko danej osoby oraz numer jej paszportu. W zasadzie nie jest to takie trudne. Możesz na przykład zmieścić oba w jednym wierszu i utworzyć listę takich wierszy: „Anna Ivanovna Reshetnikova, 4211 717171”. Ale to rozwiązanie ma dwie wady. Po pierwsze, możemy potrzebować funkcji wyszukiwania paszportu. A przy takim formacie przechowywania informacji będzie to problematyczne. Po drugie, nic nie stoi na przeszkodzie, aby stworzyć dwie różne osoby z tymi samymi numerami paszportów. I to jest najpoważniejsza wada naszego rozwiązania. Takie sytuacje należy całkowicie wykluczyć, nie ma dwóch osób o tym samym numerze paszportu. Tutaj z pomocą przychodzi Mapa i jej zadeklarowane funkcje (przechowywanie danych w parze w formacie „klucz” – „wartość”). Przyjrzyjmy się najczęstszej implementacji Map – klasie Java HashMap .Tworzenie HashMap w Javie i praca z klasą
Ta implementacja jest bardzo prosta do stworzenia:public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
Tutaj stworzyliśmy słownik, w którym elementy będą przechowywane w formacie „liczba-ciąg”. Liczba będzie kluczem, a ciąg będzie wartością. Wskazaliśmy także, jaki typ kluczy będziemy mieli ( Integer
) i jaki rodzaj wartości będziemy mieli ( String
). Dlaczego tak jest? Po pierwsze, klucz w HashMap jest zawsze unikalny . U nas sprawdzi się to znakomicie, ponieważ możemy wykorzystać numer paszportu jako klucz i uniknąć duplikatów. A linia z pełnym imieniem i nazwiskiem będzie pełnić rolę wartości (imiona i nazwiska różnych osób można łatwo powtórzyć, dla nas nie ma w tym nic złego).
Dodanie nowej pary do HashMap
To zadanie wygląda następująco:public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
System.out.println(passportsAndNames);
}
}
Do tego służy metoda put()
. Dodatkowo HashMap ma przesłoniętą metodę, toString()
dzięki czemu można ją wydrukować na konsoli. Dane wyjściowe będą wyglądać następująco: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Iwan Michajłowicz Serebryakow}
Funkcje kluczy HashMap
Sprawdźmy teraz, czy klucze są naprawdę unikalne? Spróbujmy dodać nowy element z kluczem już na mapie:public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
passportsAndNames.put(162348, „Wiktor Michajłowicz Stychkin”);//powtórz klawisz
System.out.println(passportsAndNames);
}
Wyjście: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Viktor Michajłowicz Stychkin} Poprzedni element z kluczem 162348, jak widać, został nadpisany. „Klucz” nie bez powodu został nazwany kluczem. Dostęp do wartości w HashMapie odbywa się za pomocą klucza (ale nie odwrotnie – klucza nie można uzyskać za pomocą wartości, ponieważ wartości mogą się duplikować). Widać to wyraźnie na przykładach pobierania elementu, a także usuwania elementu z HashMap:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
String lidiaName = passportsAndNames.get(212133);
System.out.println(lidiaName);
passportsAndNames.remove(162348);
System.out.println(passportsAndNames);
}
Aby pobrać wartość lub usunąć parę ze słownika, musimy przekazać do get()
metod remove()
dokładnie unikalny klucz odpowiadający tej wartości . W HashMap nie ma indeksów numerycznych, jak w tablicach lub listach - dostęp do wartości odbywa się za pomocą klucza. Wyjście z konsoli: Lidiya Arkadyevna Bublikova {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump}
Sprawdzanie obecności klucza i wartości
W klasach ArrayList i LinkedList mogliśmy sprawdzić, czy lista zawiera konkretny element. HashMap również pozwala to zrobić i dla obu części pary: ma metodycontainsKey()
(sprawdza obecność klucza) i containsValue()
(sprawdza obecność wartości).
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
System.out.println(passportsAndNames.containsKey(11111));
System.out.println(passportsAndNames.containsValue(„Donald John Trump”));
}
Wynik: fałsz, prawda
Uzyskiwanie listy wszystkich kluczy i wartości
Kolejną wygodną funkcją HashMap jest to, że możesz osobno uzyskać listę wszystkich kluczy i wszystkich wartości . W tym celu stosuje się metodykeySet()
i values()
:
public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
Set<Integer> keys = passportsAndNames.keySet();
System.out.println("Klucze: " + keys);
ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
System.out.println("Wartości: " + values);
}
}
Klucze są wyodrębniane do kolekcji Set
. Jego osobliwością jest to, że nie może zawierać powtarzających się elementów. Teraz najważniejszą rzeczą do zapamiętania jest to, że listę wszystkich kluczy można wyjąć z HashMap do osobnej kolekcji. W przykładzie zapisaliśmy wartości na normal ArrayList
. Dane wyjściowe konsoli: Klawisze: [212133, 8082771, 162348] Wartości: [Lidiya Arkadyevna Bublikova, Donald John Trump, Ivan Mikhailovich Serebryakov] Metody size()
robią clear()
dokładnie to samo, co w poprzednich strukturach, przez które przeszliśmy: pierwsza zwraca elementy liczbowe w słowniku w danym momencie, drugi usuwa wszystkie elementy.
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
System.out.println(passportsAndNames.size());
passportsAndNames.clear();
System.out.println(passportsAndNames);
}
Wynik: 3 {} Aby sprawdzić, czy nasza HashMap ma przynajmniej jeden element, możemy skorzystać z metody isEmpty()
:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
if (!passportsAndNames.isEmpty()) {
System.out.println(passportsAndNames);
}
}
Wyjście: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Michajłowicz Serebryakov} Teraz wyprowadzimy na konsolę dopiero po wstępnej weryfikacji :)
Połączenie dwóch map w jedną
Kolejną interesującą kwestią jest to, że dwie mapy można połączyć w jedną . Jest na to metodaputAll()
. Wywołujemy to na pierwszej HashMap , drugą przekazujemy jako argument, a elementy z drugiej zostaną dodane do pierwszej:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
HashMap<Integer, String> passportsAndNames2 = new HashMap<>();
passportsAndNames.put(212133, „Lidia Arkadiewna Bublikowa”);
passportsAndNames.put(162348, „Iwan Michajłowicz Serebryakow”);
passportsAndNames.put(8082771, „Donald John Trump”);
passportsAndNames2.put(917352, „Aleksiej Andriejewicz Ermakow”);
passportsAndNames2.put(925648, „Maksym Olegowicz Arkharow”);
passportsAndNames.putAll(passportsAndNames2);
System.out.println(passportsAndNames);
}
Dane wyjściowe: {917352=Aleksiej Andriejewicz Ermakow, 212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 925648=Maxim Olegovich Arkharov, 162348=Iwan Michajłowicz Serebryakow} Wszystkie elementy paszportówAndNames2 zostały skopiowane do paszportówAndNames . Spójrzmy teraz na bardziej skomplikowany przykład. Mianowicie iteruj po HashMap w pętli.
for (Map.Entry entry: passportsAndNames.entrySet()) {
System.out.println(entry);
}
Interfejs Map.Entry
oznacza po prostu parę klucz-wartość wewnątrz słownika. Metoda entrySet()
zwraca listę wszystkich par w naszej HashMap (ponieważ nasza mapa składa się właśnie z takich par Entry, iterujemy po parach, a nie oddzielnie kluczach lub wartościach). Wniosek: 212133=Lidiya Arkadyevna Bublikova 8082771=Donald John Trump 162348=Iwan Michajłowicz Serebryakow Zapisz ten artykuł na przyszłość: https://habr.com/ru/post/128017/ Teraz jest za wcześnie, aby go przeczytać, ale w przyszłości , kiedy nauczysz się korzystać z HashMap, pomoże ci to zrozumieć, jak ta struktura danych działa od wewnątrz. Nie zapomnij także sprawdzić oficjalnej dokumentacji Oracle na HashMap.
GO TO FULL VERSION