Java Academy · Lektion

EnumSet og EnumMap

Brug EnumSet og EnumMap til effektive, typesikre enum-baserede samlinger.

Lektion 4 af 413 trin

EnumSet og EnumMap er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.

EnumSet og EnumMap

EnumSet og EnumMap er stærkt optimerede samlingsimplementeringer til enums. Internt bruger de bitvektorer – de er derfor meget hurtigere end HashSet/HashMap til enum-nøgler.

EnumSet: Oprettelse af mængder

EnumSet indeholder fabriksmetoder til at oprette mængder af enum-konstanter.

import java.util.*;

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

EnumSet<Day> weekdays  = EnumSet.range(Day.MON, Day.FRI);
EnumSet<Day> weekend   = EnumSet.of(Day.SAT, Day.SUN);
EnumSet<Day> allDays   = EnumSet.allOf(Day.class);
EnumSet<Day> noDays    = EnumSet.noneOf(Day.class);

System.out.println(weekdays); // [MON, TUE, WED, THU, FRI]
System.out.println(weekend);  // [SAT, SUN]
System.out.println(allDays.size()); // 7

EnumSet: Mængdeoperationer

EnumSet understøtter almindelige mængdeoperationer – union, snit og komplement. De er ekstremt hurtige på grund af bitvektorimplementeringen.

import java.util.*;

enum Permission { READ, WRITE, DELETE, ADMIN, EXPORT }

EnumSet<Permission> userPerms  = EnumSet.of(Permission.READ, Permission.WRITE);
EnumSet<Permission> adminPerms = EnumSet.allOf(Permission.class);

// Complement
EnumSet<Permission> missing = EnumSet.complementOf(userPerms);
System.out.println("Missing: " + missing);
// Missing: [DELETE, ADMIN, EXPORT]

// Intersection (retain)
EnumSet<Permission> shared = EnumSet.copyOf(userPerms);
shared.retainAll(adminPerms);
System.out.println("Shared: " + shared); // [READ, WRITE]

EnumMap: Knytning af enums til værdier

EnumMap bruger enumets ordinalværdi som indeks i et array internt – opslag med O(1), som er hurtigere end HashMap.

import java.util.*;

enum Quarter { Q1, Q2, Q3, Q4 }

EnumMap<Quarter, Double> revenue = new EnumMap<>(Quarter.class);
revenue.put(Quarter.Q1, 125_000.0);
revenue.put(Quarter.Q2, 148_500.0);
revenue.put(Quarter.Q3, 132_750.0);
revenue.put(Quarter.Q4, 175_200.0);

double total = revenue.values().stream()
    .mapToDouble(Double::doubleValue).sum();
System.out.printf("Annual revenue: $%.0f%n", total);
// Annual revenue: $581450

EnumMap: Gennemløb i rækkefølge

EnumMap gennemløber altid nøglerne i enum-deklarationsrækkefølge – ikke indsættelsesrækkefølge eller hash-rækkefølge.

import java.util.*;

enum Month { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }

EnumMap<Month, Integer> salesUnits = new EnumMap<>(Month.class);
salesUnits.put(Month.MAR, 1420);
salesUnits.put(Month.JAN, 980);
salesUnits.put(Month.FEB, 1105);

// Iterates JAN, FEB, MAR (declaration order, not insertion order)
for (var entry : salesUnits.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
// JAN: 980
// FEB: 1105
// MAR: 1420

Tilladelsessystem med EnumSet

Et rollebaseret tilladelsessystem, der bruger EnumSet til effektive tilladelseskontroller og en ren API-udformning.

import java.util.*;

enum Permission { READ, WRITE, DELETE, PUBLISH, ADMIN }

record Role(String name, EnumSet<Permission> permissions) {
    boolean can(Permission p) { return permissions.contains(p); }
}

Role editor = new Role("Editor",
    EnumSet.of(Permission.READ, Permission.WRITE, Permission.PUBLISH));
Role viewer = new Role("Viewer",
    EnumSet.of(Permission.READ));

System.out.println(editor.can(Permission.WRITE));  // true
System.out.println(viewer.can(Permission.DELETE)); // false

Funktionsflag med EnumMap

EnumMap er perfekt til systemer med funktionsflag: hurtigt opslag med O(1) ved hjælp af enum-nøgler.

import java.util.*;

enum Feature { DARK_MODE, BETA_EDITOR, AI_SUGGESTIONS, EXPORT_PDF }

class FeatureFlags {
    private final EnumMap<Feature, Boolean> flags = new EnumMap<>(Feature.class);

    public FeatureFlags() {
        for (Feature f : Feature.values()) flags.put(f, false);
    }

    public void enable(Feature f)  { flags.put(f, true); }
    public void disable(Feature f) { flags.put(f, false); }
    public boolean isEnabled(Feature f) { return flags.getOrDefault(f, false); }
}

FeatureFlags ff = new FeatureFlags();
ff.enable(Feature.DARK_MODE);
System.out.println(ff.isEnabled(Feature.DARK_MODE));      // true
System.out.println(ff.isEnabled(Feature.AI_SUGGESTIONS)); // false

Ydeevne: EnumSet kontra HashSet

EnumSet bruger en enkelt long-bitmaske (til enums med <=64 konstanter) – operationerne er O(1)-bitoperationer. HashSet bruger hash-buckets – det er langsommere og har større ekstraomkostninger.

import java.util.*;

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

// EnumSet: bit operations on a long value
EnumSet<Day> workDays = EnumSet.range(Day.MON, Day.FRI);

// HashSet: hash table with boxing overhead
Set<Day> hashWorkDays = new HashSet<>(Arrays.asList(
    Day.MON, Day.TUE, Day.WED, Day.THU, Day.FRI));

// Both work, but EnumSet is ~5x faster for contains/add/remove
// and uses less memory
System.out.println(workDays.contains(Day.SAT));     // false
System.out.println(workDays.contains(Day.MON));     // true

EnumMap getOrDefault og computeIfAbsent

EnumMap understøtter alle Map-operationer, herunder getOrDefault, computeIfAbsent og merge.

import java.util.*;

enum Category { FOOD, ELECTRONICS, CLOTHING, BOOKS }

EnumMap<Category, List<String>> catalog = new EnumMap<>(Category.class);

// computeIfAbsent creates the list on first use
catalog.computeIfAbsent(Category.BOOKS, k -> new ArrayList<>()).add("Clean Code");
catalog.computeIfAbsent(Category.BOOKS, k -> new ArrayList<>()).add("Effective Java");
catalog.computeIfAbsent(Category.ELECTRONICS, k -> new ArrayList<>()).add("Laptop");

System.out.println(catalog.get(Category.BOOKS));
// [Clean Code, Effective Java]
System.out.println(catalog.getOrDefault(Category.FOOD, List.of()));
// []

Multimap-mønster med EnumMap

Kombinér EnumMap med List-værdier for at oprette en multimap med enum-nøgler – effektiv gruppering af elementer efter kategori.

import java.util.*;
import java.util.stream.*;

enum Priority { LOW, NORMAL, HIGH, URGENT }
record Task(String name, Priority priority) {}

List<Task> tasks = List.of(
    new Task("Fix login bug", Priority.URGENT),
    new Task("Update docs",   Priority.LOW),
    new Task("Add unit tests",Priority.NORMAL),
    new Task("Deploy hotfix", Priority.URGENT)
);

// Group by priority into EnumMap
EnumMap<Priority, List<Task>> byPriority = tasks.stream()
    .collect(Collectors.groupingBy(Task::priority,
        () -> new EnumMap<>(Priority.class),
        Collectors.toList()));

byPriority.forEach((p, ts) ->
    System.out.println(p + ": " + ts.stream().map(Task::name).collect(Collectors.joining(", "))));

Hvornår skal du bruge EnumSet kontra EnumMap

Her er en oversigt over, hvornår du skal vælge hver af dem:

  • EnumSet: når du har brug for en mængde enum-værdier – tilladelser, aktive funktioner eller valgte dage
  • EnumMap: når du knytter hver enum-konstant til en værdi – konfiguration pr. funktion, point pr. niveau eller elementer pr. kategori
  • Begge: foretræk dem frem for HashSet/HashMap til enum-nøgler – de er hurtigere, bruger mindre hukommelse og bevarer rækkefølgen

Hurtig kontrol

Hvilken intern datastruktur bruger EnumSet til enums med højst 64 konstanter?

Opsummering: EnumSet og EnumMap

Vigtigste pointer:

  • EnumSet bruger en bitvektor – ekstremt hurtigt til små enum-mængder
  • EnumSet.of(), range(), allOf() og noneOf() er almindelige fabriksmetoder
  • EnumMap bruger arrays med ordinalindekser – opslag med O(1), sorteret efter deklarationsrækkefølge
  • Brug EnumSet til tilladelsesmængder, funktionsflag og filtrering efter ugedag
  • Brug EnumMap til konfiguration pr. kategori, pointtabeller og tilknytning fra funktion til værdi
  • Begge bevarer enum-deklarationsrækkefølgen og er mere effektive end hash-baserede samlinger
Gratis at komme i gang

Lær Java med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
104
Lektioner
374

Ofte stillede spørgsmål

Er lektionen “EnumSet og EnumMap” gratis?

Ja — hele teksten til “EnumSet og EnumMap” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “EnumSet og EnumMap”?

Brug EnumSet og EnumMap til effektive, typesikre enum-baserede samlinger. Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Java Academy?

Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.

Hvor lang tid tager lektionen “EnumSet og EnumMap”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Java Academy-lektion?

Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Definition og brug af enums
  2. Enums med felter og metoder
  3. Switch-udtryk med enums
  4. EnumSet og EnumMap
← Tilbage til Java Academy