Kurs Java

Kolekcje - Mapy

Zgodnie z tym, o czym pisaliśmy już na łamach portalu, mapy nie są takimi samymi kolekcjami jak zbiory i listy, ponieważ w przeciwieństwie do nich mapy nie implementują interfejsu Collection. Nie zmienia to jednak faktu, że służą one do przechowywania kolekcji danych i z tego powodu przypisujemy je do tej samej kategorii (merytorycznie). Stąd też tytuł tego rozdziału brzmi Kolekcje - Mapy.

No dobrze to teraz przejdźmy do konkretów i wyjaśnijmy sobie czym są mapy i dlaczego są szalenie istotne w programowaniu w Javie. Najważniejszą kwestią i zarazem pewną nowością w stosunku do poprzednich kolekcji jest to, że mapy przechowują pary klucz - wartość w postaci obiektów o nazwie entry. Zwyczajowo mówimy zatem, że mapa jest kolekcją entries, gdzie każde entry składa się z pary:

Klucz - Wartość (Key - Value)

Na przykład tworząc mapę filmów w wypożyczalni VoD moglibyśmy ustalić klucze w postaci numerów identyfikujących, a za wartości przyjąć nazwy filmów. Owe numery to po prostu kolejno rosnące liczby (tutaj wymyślone), nadawane filmom wcześniej podczas wprowadzania ich do bazy.

849, Avatar 123, Szeregowiec Ryan 543, Mission Impossible
Takie rozwiązanie daje nam dużo możliwości. Pozwala na przykład pobrać z mapy tytuł filmu poprzez podanie jego numeru, jak również umożliwia wprowadzenie kolejnych par z nowymi numerami i nowymi tytułami filmów. Do tego służą oczywiście osobne metody, które wskażemy nieco niżej. Najpierw zobaczmy jakie są cechy charakterystyczne map:
  • Nie są dozwolone duplikaty kluczy.

  • Wartości mogą się duplikować.

  • Mogą być sortowalne lub nie - zależy od konkretnej implementacji interfejsu.

  • Klucze mogą być null-ami lub nie - zależy od konkretnej implementacji interfejsu (TreeMapy nie pozwalają na nulle).


W tym miejscu przypomnijmy jeszcze o hierarchii, którą przedstawialiśmy w rozdziale Kolekcje - Wprowadzenie. Wspomnieliśmy tam, że mapy implementują interfejs Map, a także że istnieje interfejs SortedMap, który dotyczy map posortowanych. Innymi słowy, każda implementacja tych interfejsów dostarczy ciała metod, które są w nich zdefiniowane.

Popularne implementacje map

Najpopularniejszymi mapami są implementacje dostarczane przez klasy:
  • HashMap z pakietu java.util

    Bardzo często stosowana implementacja. Elementy są nieposortowane. Ich kolejność nie odpowiada również kolejności wkładania do zbioru. Może przechowywać jednego null-a wśród kluczy.

  • LinkedHashMap z pakietu java.util

    Implementacja przechowująca elementy w kolejności ich dodawania. Rozszerza klasę HashMap. Zatem może być przydatna jeśli zależy nam zarówno na unikalności kluczy jak i na tworzeniu historii unikalnych wpisów. Może przechowywać jednego null-a wśród kluczy.
  • TreeMap z pakietu java.util

    Nie pozwala na przechowywanie nulla w miejscu klucza. Elementy są przechowywane pod postacią drzewa. Elementy są poukładane według kluczy w sposób posortowany (rosnąco). Przydaje się gdy chcemy zapewnić unikalność elementów oraz podstawowe sortowanie.

Tworzenie mapy

Tak jak w przypadku innych kolekcji dobrą praktyką jest zadeklarowanie instancji mapy z parametrem typu. Należy pamiętać, że deklarujemy dwa typy. Jeden dla kluczy, a drugi dla wartości.
Map<Object, Object> mapOfAnything = new HashMap<Object,Object>();
Map<Integer, String> linkedWordsWithIds = new LinkedHashMap<Integer,String>();
Map<Integer, String> sortedWordsWithIds = new TreeMap<Integer,String>();
W dwóch ostatnich przykładach zadeklarowaliśmy typy tak, by umożliwić przechowywanie liczb (integerów) jako kluczy oraz stringów jako wartości. W ten sposób moglibyśmy stworzyć mapę dla wspomnianego wcześniej przykładu z filmami VoD.

Java 7

Od Javy 7 możemy usunąć parametr typu po prawej stronie, co upraszcza zapis do następującej postaci:
Map<Object, Object> mapOfAnything = new HashMap<>();
Map<Integer, String> linkedWordsWithIds = new LinkedHashMap<>();
Map<Integer, String> sortedWordsWithIds = new TreeMap<>();

Java 9

Od Javy 9 możemy utworzyć mapę z ustalonego zestawu elementów:
Map<Integer, String> movies = Map.of(1, "Avatar");

Java 10

Od Javy 10 można jeszcze bardziej skrócić tworzenie kolekcji używając słowa kluczowego var:
var movies = new HashMap<Integer, String>();

Podstawowe operacje na mapach

Podstawowymi operacjami jakie możemy wykonywać na mapach jest dodawanie, pobieranie oraz usuwanie elementów. Operacje te są realizowane przez następujące metody:
  • put(<obiekt>, <obiekt>)

    Umożliwia ona dodanie elementu do mapy. Co ważne - wymagane jest dodanie elementów tych samych typów (lub podtypów) co parametry typów zadeklarowanych przez mapę. Metoda ta umożliwia również aktualizację obiektu w mapie. Wprowadzając do mapy parę o tym samym kluczu, ale innej wartości, podmieniamy de facto tę wartość.
    Map<Integer, String> movies = new HashMap<Integer, String>();
    // Poniższe elementy zostaną dodane do mapy - wszystkie klucze są typu Integer, a wartości typu String:
    movies.put(1, "Joker");
    movies.put(2, "Jurassic World");
    movies.put(3, "Psy 3");
    
    //Po wykonaniu poniższej linijki podmienimy film dla identyfikatora 2:
    movies.put(2, "Nietykalni");
    
    // Poniższy element nie zostanie dodany do mapy - kompilator zgłosi błąd 
    // (404 jest liczbą a nie stringiem):
    movies.put(4, 404);
    
  • get(<obiekt>)

    Metoda pobiera element z mapy poprzez podanie wybranego obiektu klucza. Poniższy zapis zwróci obiekt z tekstem "Joker".
    String movie = movies.get(1);
    
  • remove(<obiekt>)

    Metoda usuwa element z mapy poprzez podanie wybranego obiektu klucza. Poniższy zapis usunie film "Psy 3", który wyżej dodaliśmy z kluczem 3.
    movies.remove(3);
    
Podobnie jak to miało miejsce w przypadku innych kolekcji, wymieniliśmy kilka podstawowych metod, które pozwalają na prostą pracę z mapami. Uruchamiając mechanizm podpowiedzi w IDE - na przykład w IntelliJ - można łatwo poznać jakie metody są dostępne (obrazek zawiera podpowiedź dla mapy movies).

Należy przy tym pamiętać, że akurat w kontekście map zmieniło się bardzo dużo począwszy od Javy 8. Wprowadzone tam przetwarzanie danych na strumieniach to zaledwie początek zmian. Pojawiło się również kilka zupełnie nowych metod, które dają o wiele większe możliwości w pracy z tymi strukturami. Wszystkiego dowiesz się z Kursu Javy 8 do 17, w którym poświęciliśmy temu zagadnieniu osobny rozdział z wieloma ciekawymi przykładami.
Lista metod mapy

Przeglądanie zawartości mapy

Mapy nie implementują interfejsu Iterable, ale i tak można je w łatwy sposób przeglądać za pomocą iteratora. Przypominamy, że jego działanie polega na przeglądaniu kolekcji dopóki po danym elemencie występuje kolejny element. Pobranie bieżącego elementu i przejście do następnego wykonywane jest za pomocą metody next.

W przypadku map - aby użyć iteratora - najpierw pobieramy z mapy zbiór entries. Wspominaliśmy na początku rozdziału, że entry to obiekt zawierający parę klucz - wartość. Wszystkie entries tworzą zbiór (czyli znany Wam już Set), a jak wiemy zbiory możemy iterować i właśnie tak podchodzimy do tematu:

Map<Integer, String> movies = new HashMap<Integer, String>();
movies.put(1, "Joker");
movies.put(2, "Jurassic World");
movies.put(3, "Psy 3");

Set<Map.Entry<Integer, String>> entries = movies.entrySet();
Iterator<Map.Entry<Integer, String>> moviesIterator = entries.iterator();

while(moviesIterator.hasNext()) {
    Map.Entry<Integer, String> entry = moviesIterator.next();
    System.out.println(entry.getKey());
    System.out.println(entry.getValue());    
}
Każde kolejne wywołanie metody next powoduje zwrócenie obiektu typu Entry. Mając dostęp do tego obiektu możemy pobrać z niego klucz lub wartość. W ten sposób drukujemy obiekty na konsoli.

Obiekty entries możemy też przeglądać za pomocą udoskonalonej pętli for (for-each), albo też począwszy od Javy 8 za pomocą strumieni.
Zdjęcie autora
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Masz pytanie dotyczące tego rozdziału? Zadaj je nam!
Masz pytanie dotyczące prezentowanego materiału?
Coś jest dla Ciebie niejasne i Twoje wątpliwości przeszkadzają Ci w pełnym zrozumieniu treści?
Napisz do nas maila, a my chętnie znajdziemy odpowiednie rozwiązanie.
Najciekawsze pytania wraz z odpowiedziami będziemy publikować pod rozdziałem.
Nie czekaj. Naucz się programować jeszcze lepiej.
kursjava@javappa.com

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE