0Pricing
Java Academy · Lekcja

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.

Wszystkie lekcje w tym kursie

  1. Enummy z polami i metodami
  2. Metody abstrakcyjne w enumach
  3. EnumSet
  4. EnumMap
← Powrót do Java Academy