Java Academy · leksjon

EnumSet og EnumMap

Bruk EnumSet og EnumMap for effektive, typesikre enum-baserte samlinger.

Leksjon 4 av 413 trinn

EnumSet og EnumMap er en gratis leksjon i Java Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Java Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Java Academy inneholder totalt 4 leksjoner.

EnumSet og EnumMap

EnumSet og EnumMap er svært optimaliserte samlingsimplementasjoner for enumtyper. De bruker bitvektorer internt – og er mye raskere enn HashSet/HashMap for enumnøkler.

EnumSet: Opprette sett

EnumSet tilbyr fabrikkmetoder for å opprette sett med enumkonstanter.

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: Settopsjoner

EnumSet støtter standardoperasjoner på mengder – union, snitt og komplement. Disse er svært raske takket være implementasjonen med bitvektorer.

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: Knytte enumkonstanter til verdier

EnumMap bruker enumens ordinalverdi som en array-indeks internt – oppslag med O(1), raskere enn 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: Iterere i riktig rekkefølge

EnumMap itererer alltid over nøkler i den rekkefølgen enumkonstantene er deklarert – ikke i innsettingsrekkefølge eller hash-rekkefø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

Tillatelsessystem med EnumSet

Et rollebasert tillatelsessystem som bruker EnumSet for effektive tillatelseskontroller og et ryddig API-design.

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

Funksjonsflagg med EnumMap

EnumMap passer perfekt til systemer med funksjonsflagg: raske oppslag med O(1) ved bruk av enumnøkler.

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

Ytelse: EnumSet kontra HashSet

EnumSet bruker en enkelt long-bitmaske (for enumtyper med <=64 konstanter) – operasjonene er bitoperasjoner med O(1). HashSet bruker hash-bøtter og er tregere med mer overhead.

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 støtter alle Map-operasjoner, inkludert 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

Kombiner EnumMap med List-verdier for å opprette en enumnøkkelbasert multimap – en effektiv måte å gruppere elementer etter kategori på.

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(", "))));

Når bør du bruke EnumSet kontra EnumMap

Oppsummering av når du bør velge de ulike typene:

  • EnumSet: når du trenger et sett med enumverdier – tillatelser, aktive funksjoner eller valgte dager
  • EnumMap: når du knytter hver enumkonstant til en verdi – konfigurasjon per funksjon, poengsum per nivå eller elementer per kategori
  • Begge: foretrekkes fremfor HashSet/HashMap for enumnøkler – de er raskere, bruker mindre minne og opprettholder rekkefølgen

Hurtigsjekk

Hvilken intern datastruktur bruker EnumSet for enumtyper med 64 eller færre konstanter?

Oppsummering: EnumSet og EnumMap

Viktige punkter:

  • EnumSet bruker en bitvektor – svært raskt for små enumsett
  • EnumSet.of(), range(), allOf() og noneOf() er vanlige fabrikkmetoder
  • EnumMap bruker ordinalindekserte arrayer – oppslag med O(1), sortert etter deklarasjonsrekkefølgen
  • Bruk EnumSet for tillatelsessett, funksjonsflagg og filtrering etter ukedag
  • Bruk EnumMap for konfigurasjon per kategori, poengtabeller og kobling fra funksjon til verdi
  • Begge opprettholder enumens deklarasjonsrekkefølge og er mer effektive enn hashbaserte samlinger
Gratis å komme i gang

Lær deg Java med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
104
Leksjoner
374

Ofte stilte spørsmål

Er leksjonen «EnumSet og EnumMap» gratis?

Ja – hele teksten i «EnumSet og EnumMap» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Java Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Java Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «EnumSet og EnumMap»?

Bruk EnumSet og EnumMap for effektive, typesikre enum-baserte samlinger. Du øver på Java Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Java Academy?

Ingen tidligere erfaring er nødvendig. Java Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «EnumSet og EnumMap»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Java Academy-leksjonen?

Ja. Alle Java Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Definere og bruke enum-typer
  2. Enum-typer med felt og metoder
  3. Switch-uttrykk med enum-typer
  4. EnumSet og EnumMap
← Tilbake til Java Academy