EnumSet ja EnumMap
Käytä EnumSet- ja EnumMap-kokoelmia tehokkaaseen ja tyyppiturvalliseen enum-pohjaiseen käsittelyyn.
EnumSet ja EnumMap on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
EnumSet ja EnumMap
EnumSet ja EnumMap ovat erittäin optimoituja enumien kokoelmatoteutuksia. Ne käyttävät sisäisesti bittivektoreita — enum-avaimia käytettäessä ne ovat paljon nopeampia kuin HashSet/HashMap.
EnumSet: joukkojen luominen
EnumSet tarjoaa tehdasmetodeja enum-vakioiden sisältämien joukkojen luomiseen.
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()); // 7EnumSet: joukko-operaatiot
EnumSet tukee tavallisia joukko-operaatioita — unionia, leikkausta ja komplementtia. Bittivektoritoteutuksen ansiosta nämä operaatiot ovat erittäin nopeita.
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: enumien yhdistäminen arvoihin
EnumMap käyttää sisäisesti enum-vakiota taulukon indeksinä — haku on O(1) ja nopeampaa kuin HashMapissa.
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: $581450EnumMap: iterointi järjestyksessä
EnumMap käy avaimet aina läpi enumien määritysjärjestyksessä — ei lisäys- tai hash-järjestyksessä.
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: 1420Käyttöoikeusjärjestelmä EnumSetillä
Roolipohjainen käyttöoikeusjärjestelmä, jossa EnumSetiä käytetään tehokkaisiin käyttöoikeustarkistuksiin ja selkeään API-suunnitteluun.
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)); // falseOminaisuusliput EnumMapillä
EnumMap sopii erinomaisesti ominaisuuslippujärjestelmiin: enum-avaimilla saadaan nopea O(1)-haku.
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)); // falseSuorituskyky: EnumSet vs. HashSet
EnumSet käyttää yhtä long-bittimaskia (enum-tyypeille, joissa on <=64 vakiota) — operaatiot ovat O(1)-bittioperaatioita. HashSet käyttää hash-ämpäreitä, joten siinä on enemmän ylimääräistä käsittelyä ja se on hitaampi.
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)); // trueEnumMap getOrDefault ja computeIfAbsent
EnumMap tukee kaikkia Map-operaatioita, kuten getOrDefault-, computeIfAbsent- ja merge-operaatioita.
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-malli EnumMapillä
Yhdistämällä EnumMapin List-arvoihin voitte luoda enum-avaimellisen multimapin, jolla alkiot ryhmitellään tehokkaasti luokan mukaan.
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(", "))));Milloin käyttää EnumSetiä ja milloin EnumMapiä
Yhteenveto valintaperusteista:
- EnumSet: kun tarvitsette enum-arvojen joukon — esimerkiksi käyttöoikeuksia, aktiivisia ominaisuuksia tai valittuja viikonpäiviä
- EnumMap: kun yhdistätte jokaisen enum-vakion arvoon — esimerkiksi ominaisuuskohtaisiin asetuksiin, tasokohtaisiin pisteisiin tai luokkakohtaisiin alkioihin
- Molemmat: suosikaa niitä HashSetin/HashMapin sijaan enum-avaimilla — ne ovat nopeampia, käyttävät vähemmän muistia ja säilyttävät järjestyksen
Pikatarkistus
Mitä sisäistä tietorakennetta EnumSet käyttää enum-tyypeille, joissa on enintään 64 vakiota?
Kertaus: EnumSet ja EnumMap
Tärkeimmät opit:
- EnumSet käyttää bittivektoria — se on erittäin nopea pienille enum-joukoille
- EnumSet.of(), range(), allOf() ja noneOf() ovat yleisiä tehdasmetodeja
- EnumMap käyttää ordinaalin mukaan indeksoituja taulukoita — haku on O(1), ja avaimet ovat määritysjärjestyksessä
- Käyttäkää EnumSetiä käyttöoikeusjoukkoihin, ominaisuuslippuihin ja viikonpäivien suodatukseen
- Käyttäkää EnumMapiä luokkakohtaisiin asetuksiin, pisteytystaulukoihin ja ominaisuuden yhdistämiseen arvoon
- Molemmat säilyttävät enumien määritysjärjestyksen ja ovat tehokkaampia kuin hash-pohjaiset kokoelmat
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”EnumSet ja EnumMap” ilmainen?
Kyllä – oppitunnin ”EnumSet ja EnumMap” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”EnumSet ja EnumMap”?
Käytä EnumSet- ja EnumMap-kokoelmia tehokkaaseen ja tyyppiturvalliseen enum-pohjaiseen käsittelyyn. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”EnumSet ja EnumMap”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Enum-tyyppien määrittäminen ja käyttäminen
- Kentät ja metodit enum-tyypeissä
- Switch-lausekkeet enum-tyypeillä
- EnumSet ja EnumMap