0Pricing
Java Academy · Lekcja

EnumSet

Szybkie operacje na zbiorach enumów

EnumSet to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 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 EnumSet

EnumSet to wyspecjalizowana implementacja Set przeznaczona wyłącznie dla typów enum.

Wewnętrznie jest wektorem bitowym: każdej stałej odpowiada jeden bit. Dzięki temu jest niezwykle szybki i oszczędny pamięciowo w porównaniu z HashSet przechowującym enumy.

import java.util.EnumSet;
import java.util.Set;

public class Main {
    enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
    public static void main(String[] args) {
        Set<Day> weekend = EnumSet.of(Day.SAT, Day.SUN);
        System.out.println(weekend);
    }
}

Tworzenie za pomocą of

Fabryka EnumSet.of(...) tworzy zbiór z wymienionych stałych. Dostępne są przeciążenia dla od jednego do pięciu elementów oraz wersja varargs.

import java.util.EnumSet;

public class Main {
    enum Perm { READ, WRITE, EXECUTE }
    public static void main(String[] args) {
        EnumSet<Perm> perms = EnumSet.of(Perm.READ, Perm.WRITE);
        System.out.println(perms);
    }
}

allOf i noneOf

Dwie kolejne fabryki:

  • allOf(Type.class) tworzy zbiór zawierający każdą stałą.
  • noneOf(Type.class) tworzy pusty zbiór gotowy do wypełnienia.
import java.util.EnumSet;

public class Main {
    enum Color { RED, GREEN, BLUE }
    public static void main(String[] args) {
        EnumSet<Color> all = EnumSet.allOf(Color.class);
        EnumSet<Color> none = EnumSet.noneOf(Color.class);
        none.add(Color.RED);
        System.out.println("all: " + all);
        System.out.println("built: " + none);
    }
}

range dla ciągłego zakresu stałych

EnumSet.range(from, to) obejmuje wszystkie stałe między dwoma punktami końcowymi, łącznie z nimi, w kolejności deklaracji.

import java.util.EnumSet;

public class Main {
    enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
    public static void main(String[] args) {
        EnumSet<Day> workdays = EnumSet.range(Day.MON, Day.FRI);
        System.out.println(workdays);
    }
}

complementOf

EnumSet.complementOf(set) zwraca zbiór wszystkich stałych, których nie ma w podanym zbiorze.

Jest to szybki sposób na odwrócenie zaznaczenia.

import java.util.EnumSet;

public class Main {
    enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
    public static void main(String[] args) {
        EnumSet<Day> work = EnumSet.range(Day.MON, Day.FRI);
        EnumSet<Day> rest = EnumSet.complementOf(work);
        System.out.println(rest);
    }
}

Operacje na zbiorach

Ponieważ EnumSet jest prawdziwą implementacją Set, można wykonywać na nim sumę, część wspólną i różnicę zbiorów za pomocą addAll, retainAll i removeAll.

Wewnętrznie operacje te są wykonywane jako szybkie operacje bitowe.

import java.util.EnumSet;

public class Main {
    enum Tag { A, B, C, D }
    public static void main(String[] args) {
        EnumSet<Tag> x = EnumSet.of(Tag.A, Tag.B, Tag.C);
        EnumSet<Tag> y = EnumSet.of(Tag.B, Tag.C, Tag.D);
        EnumSet<Tag> inter = EnumSet.copyOf(x);
        inter.retainAll(y);
        System.out.println("intersection: " + inter);
    }
}

Sprawdzanie przynależności

contains wykonuje pojedyncze sprawdzenie bitu, więc działa w czasie stałym i bardzo szybko.

import java.util.EnumSet;

public class Main {
    enum Feature { DARK_MODE, BETA, ANALYTICS }
    public static void main(String[] args) {
        EnumSet<Feature> enabled = EnumSet.of(Feature.DARK_MODE, Feature.BETA);
        System.out.println(enabled.contains(Feature.BETA));
        System.out.println(enabled.contains(Feature.ANALYTICS));
    }
}

EnumSet jako zamiennik flag

Przed wprowadzeniem EnumSet programiści używali flag bitowych typu int, takich jak READ | WRITE. EnumSet zastępuje je bezpieczeństwem typów i czytelnością.

Zyskują Państwo wydajność pól bitowych bez podatnego na błędy ręcznego maskowania.

import java.util.EnumSet;
import java.util.Set;

public class Main {
    enum Style { BOLD, ITALIC, UNDERLINE }
    static void render(Set<Style> styles) {
        System.out.println("Applying: " + styles);
    }
    public static void main(String[] args) {
        render(EnumSet.of(Style.BOLD, Style.UNDERLINE));
    }
}

Iterowanie w kolejności deklaracji

EnumSet iteruje w naturalnej kolejności stałych, czyli w kolejności ich deklaracji.

Zapewnia to przewidywalną i stabilną kolejność iteracji, w przeciwieństwie do HashSet.

import java.util.EnumSet;

public class Main {
    enum Phase { ALPHA, BETA, RC, GA }
    public static void main(String[] args) {
        EnumSet<Phase> set = EnumSet.of(Phase.GA, Phase.ALPHA, Phase.RC);
        for (Phase p : set) System.out.println(p);
    }
}

Kopie defensywne za pomocą copyOf

EnumSet.copyOf(collection) tworzy EnumSet z dowolnej kolekcji wartości enum. Należy go używać do tworzenia bezpiecznej kopii lub konwertowania obiektu List.

import java.util.EnumSet;
import java.util.List;

public class Main {
    enum Role { ADMIN, EDITOR, VIEWER }
    public static void main(String[] args) {
        List<Role> source = List.of(Role.EDITOR, Role.VIEWER);
        EnumSet<Role> roles = EnumSet.copyOf(source);
        System.out.println(roles);
    }
}

Dlaczego jest szybki

W przypadku enumów zawierających nie więcej niż 64 stałe EnumSet używa pojedynczego long jako wektora bitowego. Każda operacja wymaga jednej lub dwóch instrukcji procesora.

W przypadku zbiorów enumów zawsze należy preferować EnumSet zamiast HashSet<MyEnum>.

import java.util.EnumSet;

public class Main {
    enum Bit { B0, B1, B2, B3 }
    public static void main(String[] args) {
        EnumSet<Bit> s = EnumSet.of(Bit.B0, Bit.B2);
        // contains is a single bit-and under the hood
        System.out.println(s.contains(Bit.B2));
    }
}

Szybkie sprawdzenie

Proszę sprawdzić swoją wiedzę na temat EnumSet.

Podsumowanie

Dowiedzieli się Państwo, czym jest EnumSet:

  • To bardzo szybki i kompaktowy Set dla enumów, oparty na wektorze bitowym.
  • Fabryki: of, allOf, noneOf, range, complementOf, copyOf.
  • Iteruje w kolejności deklaracji.
  • Jest bezpiecznym typowo zamiennikiem flag bitowych typu int.

W następnej części: odpowiadający mu typ mapy, czyli EnumMap.

import java.util.EnumSet;

public class Main {
    enum X { A, B }
    public static void main(String[] args) {
        System.out.println("EnumSet recap: " + EnumSet.allOf(X.class));
    }
}

Często zadawane pytania

Czy lekcja „EnumSet” jest bezpłatna?

Tak — pełny tekst „EnumSet” 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 „EnumSet”?

Szybkie operacje na zbiorach enumów Ć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 3 z 4.

Ile czasu zajmuje lekcja „EnumSet”?

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