EnumSet และ EnumMap
ใช้ EnumSet และ EnumMap สำหรับคอลเลกชันที่อิง enum ซึ่งมีประสิทธิภาพและปลอดภัยด้านชนิดข้อมูล
EnumSet และ EnumMap เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
EnumSet และ EnumMap
EnumSet และ EnumMap เป็นการนำคอลเลกชันสำหรับอีนัมไปใช้งานที่ได้รับการปรับประสิทธิภาพสูงมาก ภายในใช้เวกเตอร์บิต จึงเร็วกว่าการใช้ HashSet/HashMap สำหรับคีย์อีนัมมาก
EnumSet: การสร้างเซต
EnumSet มีเมธอดโรงงานสำหรับสร้างเซตจากค่าคงที่ของอีนัม
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: การดำเนินการกับเซต
EnumSet รองรับการดำเนินการกับเซตมาตรฐาน ได้แก่ ยูเนียน อินเตอร์เซกชัน และส่วนเติมเต็ม การดำเนินการเหล่านี้รวดเร็วมากเนื่องจากการนำเวกเตอร์บิตไปใช้งาน
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: การจับคู่อีนัมกับค่า
EnumMap ใช้ลำดับของอีนัมเป็นดัชนีอาร์เรย์ภายใน จึงค้นหาได้ในเวลา O(1) และเร็วกว่าการใช้ 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: $581450EnumMap: การวนซ้ำตามลำดับ
EnumMap จะวนซ้ำคีย์ตามลำดับการประกาศอีนัมเสมอ ไม่ใช่ตามลำดับการแทรกหรือลำดับแฮช
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ระบบสิทธิ์ด้วย EnumSet
ระบบสิทธิ์ตามบทบาทที่ใช้ EnumSet เพื่อตรวจสอบสิทธิ์อย่างมีประสิทธิภาพและออกแบบ API ได้อย่างเป็นระเบียบ
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แฟล็กฟีเจอร์ด้วย EnumMap
EnumMap เหมาะอย่างยิ่งสำหรับระบบแฟล็กฟีเจอร์ โดยค้นหาด้วยคีย์อีนัมได้รวดเร็วในเวลา O(1)
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ประสิทธิภาพ: EnumSet เทียบกับ HashSet
EnumSet ใช้บิตมาสก์ชนิด long เพียงตัวเดียวสำหรับอีนัมที่มีค่าคงที่ไม่เกิน 64 ค่า การดำเนินการจึงเป็นการดำเนินการกับบิตในเวลา O(1) ส่วน HashSet ใช้บักเก็ตแฮช จึงช้ากว่าและมีค่าใช้จ่ายส่วนเกินมากกว่า
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)); // truegetOrDefault และ computeIfAbsent ของ EnumMap
EnumMap รองรับการดำเนินการทั้งหมดของ Map รวมถึง getOrDefault, computeIfAbsent และการผสานค่า
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()));
// []รูปแบบมัลติแมปด้วย EnumMap
รวม EnumMap เข้ากับค่าแบบ List เพื่อสร้างมัลติแมปที่ใช้คีย์อีนัม ทำให้จัดกลุ่มรายการตามหมวดหมู่ได้อย่างมีประสิทธิภาพ
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(", "))));ควรใช้ EnumSet หรือ EnumMap เมื่อใด
สรุปแนวทางเลือกใช้แต่ละชนิด:
- EnumSet: เมื่อจำเป็นต้องใช้เซตของค่าอีนัม เช่น สิทธิ์ ฟีเจอร์ที่เปิดใช้งาน หรือวันที่เลือก
- EnumMap: เมื่อต้องจับคู่ค่าคงที่ของอีนัมแต่ละค่ากับค่าอื่น เช่น การตั้งค่าต่อฟีเจอร์ คะแนนต่อลำดับ หรือรายการต่อหมวดหมู่
- ทั้งสองชนิด: ควรเลือกใช้แทน HashSet/HashMap เมื่อใช้คีย์อีนัม เพราะทำงานเร็วกว่า ใช้หน่วยความจำน้อยกว่า และรักษาลำดับได้
ตรวจสอบความเข้าใจ
EnumSet ใช้โครงสร้างข้อมูลภายในแบบใดสำหรับอีนัมที่มีค่าคงที่ไม่เกิน 64 ค่า
สรุปทบทวน: EnumSet และ EnumMap
ประเด็นสำคัญ:
- EnumSet ใช้เวกเตอร์บิต จึงรวดเร็วมากสำหรับเซตอีนัมขนาดเล็ก
- EnumSet.of(), range(), allOf(), noneOf() เป็นเมธอดโรงงานที่ใช้กันทั่วไป
- EnumMap ใช้อาร์เรย์ที่จัดทำดัชนีด้วยลำดับ จึงค้นหาได้ในเวลา O(1) และเรียงตามลำดับการประกาศ
- ใช้ EnumSet สำหรับเซตสิทธิ์ แฟล็กฟีเจอร์ และการกรองตามวันในสัปดาห์
- ใช้ EnumMap สำหรับการตั้งค่าต่อหมวดหมู่ ตารางคะแนน และการจับคู่ฟีเจอร์กับค่า
- ทั้งสองชนิดรักษาลำดับการประกาศของอีนัม และมีประสิทธิภาพมากกว่าคอลเลกชันที่ใช้แฮช
คำถามที่พบบ่อย
บทเรียน “EnumSet และ EnumMap” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “EnumSet และ EnumMap” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “EnumSet และ EnumMap”
ใช้ EnumSet และ EnumMap สำหรับคอลเลกชันที่อิง enum ซึ่งมีประสิทธิภาพและปลอดภัยด้านชนิดข้อมูล คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “EnumSet และ EnumMap” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การกำหนดและใช้งาน Enum
- Enum ที่มีฟิลด์และเมธอด
- นิพจน์ Switch กับ Enum
- EnumSet และ EnumMap