0Pricing
Java Academy · บทเรียน

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()); // 7

EnumSet: การดำเนินการกับเซต

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: $581450

EnumMap: การวนซ้ำตามลำดับ

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));     // true

getOrDefault และ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การกำหนดและใช้งาน Enum
  2. Enum ที่มีฟิลด์และเมธอด
  3. นิพจน์ Switch กับ Enum
  4. EnumSet และ EnumMap
← กลับไปที่ Java Academy