EnumMap
Wydajne mapy z kluczami typu enum
EnumMap to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Czym jest EnumMap
EnumMap to wyspecjalizowana implementacja Map, której kluczami są stałe jednego typu enum.
Wewnętrznie korzysta ze zwykłej tablicy indeksowanej wartością ordinal stałej. Dzięki temu wyszukiwanie i wstawianie są niezwykle szybkie, ponieważ nie wymagają haszowania.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum Day { MON, TUE, WED }
public static void main(String[] args) {
Map<Day, String> plan = new EnumMap<>(Day.class);
plan.put(Day.MON, "Gym");
plan.put(Day.WED, "Swim");
System.out.println(plan);
}
}Do utworzenia potrzebna jest klasa
EnumMap musi z góry znać typ klucza, dlatego konstruktor przyjmuje obiekt Class: new EnumMap<>(Day.class).
W ten sposób może dopasować rozmiar wewnętrznej tablicy do liczby stałych.
import java.util.EnumMap;
public class Main {
enum Priority { LOW, MEDIUM, HIGH }
public static void main(String[] args) {
EnumMap<Priority, Integer> counts = new EnumMap<>(Priority.class);
counts.put(Priority.HIGH, 5);
System.out.println(counts.get(Priority.HIGH));
}
}Szybkość dzięki tablicy
Ponieważ klucze są przechowywane pod adresem array[ordinal], get i put są bezpośrednimi odwołaniami do tablicy, szybszymi niż haszowanie i przeszukiwanie kubełków w HashMap.
Klucz nie jest opakowywany i nie jest wywoływana metoda hashCode.
import java.util.EnumMap;
public class Main {
enum Slot { A, B, C, D }
public static void main(String[] args) {
EnumMap<Slot, Integer> m = new EnumMap<>(Slot.class);
for (Slot s : Slot.values()) m.put(s, s.ordinal() * 10);
System.out.println(m.get(Slot.C));
}
}Iterowanie w kolejności kluczy
EnumMap iteruje po wpisach w naturalnej kolejności kluczy, czyli w kolejności ich deklaracji.
Zapewnia to stabilny i przewidywalny wynik, w przeciwieństwie do HashMap.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum Phase { PLAN, BUILD, SHIP }
public static void main(String[] args) {
Map<Phase, Integer> hours = new EnumMap<>(Phase.class);
hours.put(Phase.SHIP, 3);
hours.put(Phase.PLAN, 8);
hours.put(Phase.BUILD, 20);
for (Map.Entry<Phase, Integer> e : hours.entrySet()) {
System.out.println(e.getKey() + " = " + e.getValue());
}
}
}Klucze null są zabronione
EnumMap nie pozwala na klucze null; użycie klucza null powoduje zgłoszenie NullPointerException.
Wartości null są dozwolone, tak jak w innych mapach.
import java.util.EnumMap;
public class Main {
enum K { A, B }
public static void main(String[] args) {
EnumMap<K, String> m = new EnumMap<>(K.class);
m.put(K.A, null); // null value is fine
System.out.println("A -> " + m.get(K.A));
System.out.println("contains A: " + m.containsKey(K.A));
}
}Grupowanie za pomocą EnumMap
Częstym zastosowaniem jest zliczanie lub grupowanie według kategorii enuma. Metoda merge pozwala zwięźle tworzyć podsumowania.
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
public class Main {
enum Type { FRUIT, VEG, MEAT }
record Item(String name, Type type) {}
public static void main(String[] args) {
List<Item> items = List.of(new Item("apple", Type.FRUIT), new Item("pear", Type.FRUIT), new Item("beef", Type.MEAT));
Map<Type, Integer> counts = new EnumMap<>(Type.class);
for (Item i : items) counts.merge(i.type(), 1, Integer::sum);
System.out.println(counts);
}
}getOrDefault i computeIfAbsent
Działają wszystkie standardowe metody domyślne interfejsu Map. getOrDefault eliminuje sprawdzanie wartości null, a computeIfAbsent tworzy wartości leniwie.
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
public class Main {
enum Group { A, B }
public static void main(String[] args) {
Map<Group, List<String>> m = new EnumMap<>(Group.class);
m.computeIfAbsent(Group.A, k -> new ArrayList<>()).add("first");
System.out.println(m);
System.out.println(m.getOrDefault(Group.B, List.of()));
}
}Konstruktor kopiujący
EnumMap ma konstruktor kopiujący, który przyjmuje inną mapę. Jeśli źródłem jest EnumMap, typ klucza jest ustalany na jego podstawie.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum K { X, Y }
public static void main(String[] args) {
EnumMap<K, Integer> a = new EnumMap<>(K.class);
a.put(K.X, 1);
EnumMap<K, Integer> b = new EnumMap<>(a);
b.put(K.Y, 2);
System.out.println("copy: " + b);
}
}EnumMap a tablice indeksowane przez ordinal
Przed wprowadzeniem EnumMap używano zwykłych tablic indeksowanych przez ordinal(). To rozwiązanie jest kruche i niebezpieczne.
EnumMap zapewnia taką samą szybkość tablicy, a dodatkowo bezpieczeństwo typów, bezpieczeństwo zakresów i przejrzyste API Map.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum Season { SPRING, SUMMER, FALL, WINTER }
public static void main(String[] args) {
Map<Season, String> mood = new EnumMap<>(Season.class);
mood.put(Season.SUMMER, "sunny");
// Safer and clearer than String[] indexed by ordinal
System.out.println(mood.get(Season.SUMMER));
}
}Zagnieżdżone EnumMap
Można zagnieżdżać obiekty EnumMap, aby modelować macierz indeksowaną przez dwa enumy, na przykład tabelę przejść stanów.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum State { SOLID, LIQUID, GAS }
enum Transition { MELT, FREEZE }
public static void main(String[] args) {
Map<State, Map<Transition, State>> table = new EnumMap<>(State.class);
Map<Transition, State> solid = new EnumMap<>(Transition.class);
solid.put(Transition.MELT, State.LIQUID);
table.put(State.SOLID, solid);
System.out.println(table.get(State.SOLID).get(Transition.MELT));
}
}Wybór właściwego typu
Ogólna zasada:
- Jeśli kluczami są stałe enuma i potrzebują Państwo mapy, należy użyć EnumMap.
- Jeśli potrzebują Państwo zbioru enumów, należy użyć EnumSet.
- Jeśli kluczami są dowolne obiekty, należy użyć HashMap.
import java.util.EnumMap;
import java.util.Map;
public class Main {
enum Level { DEBUG, INFO, WARN, ERROR }
public static void main(String[] args) {
Map<Level, Integer> thresholds = new EnumMap<>(Level.class);
for (Level l : Level.values()) thresholds.put(l, l.ordinal() * 100);
System.out.println(thresholds);
}
}Szybkie sprawdzenie
Proszę sprawdzić swoją wiedzę na temat EnumMap.
Podsumowanie
Dowiedzieli się Państwo, czym jest EnumMap:
- To oparta na tablicy implementacja Map, której kluczami są stałe enumów.
- Konstruktor przyjmuje kluczowy typ Class; klucze null są niedozwolone.
- Iteruje w kolejności deklaracji.
- Jest bezpiecznym i szybkim zamiennikiem tablic indeksowanych przez ordinal.
Ukończyli Państwo zaawansowany kurs dotyczący enumów.
import java.util.EnumMap;
public class Main {
enum K { A }
public static void main(String[] args) {
EnumMap<K, String> m = new EnumMap<>(K.class);
m.put(K.A, "done");
System.out.println("EnumMap course complete: " + m.get(K.A));
}
}Często zadawane pytania
Czy lekcja „EnumMap” jest bezpłatna?
Tak — pełny tekst „EnumMap” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „EnumMap”?
Wydajne mapy z kluczami typu enum Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „EnumMap”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.