Kurs Java Podstawy - rozszerzony

Interfejs Map

Map jest interfejsem wchodzącym w skład Collections Framework Javy. W odróżnieniu od list oraz zbiorów, mapy nie implementują interfejsu Collection. Jest to związane z tym, że w mapach elementy przechowywane są w postaci par klucz-wartość, gdzie oba z tych elementów mogą być dowolnym typem obiektowym. W mapie do danego klucz może być przypisana tylko jedna wartość, gdy spróbujemy dodać kolejną wartość o tym samym kluczu to spowodujemy nadpisanie wartości już istniejącej. Przykłady to isbn-książka, pesel-osoba, id-produkt itp.

  1. Implementacje

    1. HashMap
    2. TreeMap
    3. LinkedHashMap

  2. Różnice
  3. Metody
  4. Przykład

Implementacje

map treemap hashmap linkedhashmap

HashMap

Podstawowa implementacja oparta podobnie jak HashSet o tablicę mieszaną, więc podobnie jak i ona nie gwarantuje żadnej kolejności elementów.

TreeMap

Implementacja, która zapewnia dodatkowo sortowanie na podstawie naturalnego porządku kluczy wyznaczanego przez implementację interfejsu Comparable lub zdefiniowaniu dodatkowego Comparatora. Podobnie jak TreeSet, TreeMap również wykorzystuje drzewa czerwono czarne.

LinkedHashMap

Implementacja mapy, która zapewnia zapamiętywanie kolejności dodawania elementów, co może być przydatne przy iteracji. Wykorzystuje tablicę mieszaną oraz listę wiązaną

Wszystkie implementacje wymagają prawidłowej implementacji metod equals() i hashCode() w klasie definiującej klucz.

Różnica między HashSet, TreeSet i LinkedHashSet

Wybór odpowiedniej implementacji powinien być podyktowany naszą aktualną potrzebą. HashSet jest podstawową implementacją zapewnia stałą złożoność obliczeniową podstawowych operacji takich jak wstawianie i odczyt elementów. HashMap nie gwarantuje nam niestety żadnej kolejności w sytuacji gdzie będziemy iterowali po mapie. Jeśli nam na tym zależy, to powinniśmy skorzystać z TreeMapy, która sortuje elementy mapy według porządku kluczy lub LinkedHashMapy, gdy wolimy iterować po elementach w kolejności w jakiej były one do niej dodane. TreeMapa zapewnia logarytmiczną a LinkedHashMap stałą złożoność obliczeniową podstawowych operacji.

Metody

Ponieważ mapy nie implementują interfejsu Collection to nie znajdziemy tutaj np. metody add(). Zamiast tego najważniejsze z nich to:

  • put(K key, V value) - wstawia do mapy wartość 'v' przypisaną do klucza 'k'
  • get(Object key) - zwraca wartość przypisaną do klucza 'key' lub null jeśli do takiego klucza nie jest przypisana żadna wartość
  • remove(Object key) - usuwa z mapy wartość przypisaną do klucza 'key'
  • isEmpty() - sprawdza, czy mapa jest pusta
  • size() - zwraca rozmiar (ilość elementów) mapy
  • keySet() - zwraca zbiór kluczy
  • values() - zwraca kolekcję wartości
  • Set<Map.Entry<K,V>> entrySet() - zwraca zbiór obiektów typu Map.Entry, które reprezentują kolejne rekordy w mapie na zasadzie klucz-wartość

W TreeMap znajdziemy dodatkowe metody wynikające z implementacji takie jak firstEntry(), czy firstKey(), więcej można znaleźć w dokumentacji.

Przykład

Zdefiniujmy prosty przykład, w którym stworzymy mapę przechowującą kilka wpisów reprezentujących bazę danych pewnej firmy. Rekordy przechowywane będą w niej na zasadzie par klucz-wartość, gdzie kluczami będą id pracowników a wartościami "imię nazwisko" danego pracownika. Ponieważ chcemy, aby przy wyświetlaniu pracownicy byli posortowaniu zgodnie z kolejnością kluczy, to użyjemy implementacji TreeMap.

ExampleMap.java

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class MapExample {
	public static void main(String[] args) {
		Map<Integer, String> employees = new TreeMap<>();
		employees.put(111, "Jan Kowalski");
		employees.put(333, "Wojciech Kowalski");
		employees.put(222, "Kasia Piotrowska");
		employees.put(555, "Anna Zawadzka");
		employees.put(444, "Jan Kowalski");
		
		System.out.println("Ilość pracowników: " + employees.size());
		
		Set<Integer> keySet = employees.keySet();
		System.out.println("Klucze:\n" + keySet);
		Collection<String> values = employees.values();
		System.out.println("Wartości:\n" + values);
		
		Set<Entry<Integer,String>> entrySet = employees.entrySet();
		for(Entry<Integer, String> entry: entrySet) {
			System.out.println(entry.getKey() + " : " + entry.getValue());
		}
	}
}

Po dodaniu kilku rekordów do mapy (zwróć uwagę, że dodajemy elementy bez zachowania kolejności kluczy), wyświetlamy kolejno

  • ilość rekordów wykorzystując metodę size()
  • zbiór kluczy korzystając z metody keySet() - zwróć uwagę, że zbiór jest posortowany
  • kolekcję wartości korzystając z metody values()
  • na koniec pobieramy zbiór par klucz-wartość i wyświetlamy je w czytelnej formie

mapy konsola

Komentarze