Java中的EnumSet使用实例详解

 更新时间:2026年07月09日 15:40:15   作者:有梦想的攻城狮  
EnumSet是Java中专门为枚举类型设计的高性能Set实现,它使用位向量(bit vector)在内部表示枚举集合,性能接近位标志操作,本文介绍Java中的EnumSet使用详解,感兴趣的朋友一起看看吧

1. 概述

EnumSet是Java中专门为枚举类型设计的高性能Set实现,它使用位向量(bit vector)在内部表示枚举集合,性能接近位标志操作。

2. 核心特性

2.1 基本特点

  • 专为枚举类型优化
  • 非线程安全
  • 不允许null元素
  • 迭代顺序遵循枚举声明顺序
  • 内存高效,使用位运算
  • 所有基本操作都在常数时间内完成

2.2 内部实现

public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
    implements Cloneable, java.io.Serializable {
    // 底层使用long数组存储
    // 对于64个枚举常量以内的枚举,使用单个long
    // 超过64个,使用long数组
    final Class<E> elementType;  // 枚举类型
    final Enum<?>[] universe;     // 所有枚举常量
}

3. 创建EnumSet的工厂方法

3.1 常用工厂方法

// 定义枚举类型
enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, 
    FRIDAY, SATURDAY, SUNDAY
}
enum Color {
    RED, GREEN, BLUE, YELLOW, BLACK, WHITE
}
// 1. 创建空集合
EnumSet<Day> emptySet = EnumSet.noneOf(Day.class);
// 2. 包含所有枚举值的集合
EnumSet<Day> allDays = EnumSet.allOf(Day.class);
// 3. 从指定枚举常量创建
EnumSet<Day> workDays = EnumSet.of(Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY);
EnumSet<Day> singleDay = EnumSet.of(Day.MONDAY);  // 单个元素
// 4. 创建范围集合
EnumSet<Day> weekStart = EnumSet.range(Day.MONDAY, Day.FRIDAY);
// 5. 从其他集合创建
Set<Day> otherSet = new HashSet<>(Arrays.asList(Day.MONDAY, Day.TUESDAY));
EnumSet<Day> fromCollection = EnumSet.copyOf(otherSet);
EnumSet<Day> fromEnumSet = EnumSet.copyOf(workDays);

4. 常用操作详解

4.1 添加和删除

EnumSet<Day> days = EnumSet.noneOf(Day.class);
// 添加元素
days.add(Day.MONDAY);
days.addAll(EnumSet.of(Day.TUESDAY, Day.WEDNESDAY));
// 删除元素
days.remove(Day.MONDAY);
days.removeAll(EnumSet.of(Day.TUESDAY, Day.WEDNESDAY));
// 批量操作
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
days.addAll(weekend);  // 添加周末
days.retainAll(weekend);  // 只保留周末
days.removeAll(weekend);  // 移除周末

4.2 查询操作

EnumSet<Day> days = EnumSet.of(Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY);
// 基本查询
boolean isEmpty = days.isEmpty();  // false
int size = days.size();           // 3
boolean contains = days.contains(Day.MONDAY);  // true
// 包含关系
EnumSet<Day> workDays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
boolean containsAll = workDays.containsAll(days);  // true
// 比较
EnumSet<Day> other = EnumSet.of(Day.MONDAY, Day.TUESDAY);
boolean equals = days.equals(other);  // false

4.3 集合运算

EnumSet<Day> set1 = EnumSet.of(Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY);
EnumSet<Day> set2 = EnumSet.of(Day.WEDNESDAY, Day.THURSDAY, Day.FRIDAY);
// 并集
EnumSet<Day> union = EnumSet.copyOf(set1);
union.addAll(set2);  // 周一、周二、周三、周四、周五
// 交集
EnumSet<Day> intersection = EnumSet.copyOf(set1);
intersection.retainAll(set2);  // 周三
// 差集
EnumSet<Day> difference = EnumSet.copyOf(set1);
difference.removeAll(set2);  // 周一、周二
// 对称差(异或)
EnumSet<Day> complement = EnumSet.copyOf(set1);
complement.removeAll(set2);  // 先从set1中移除set2
EnumSet<Day> temp = EnumSet.copyOf(set2);
temp.removeAll(set1);  // 再从set2中移除set1
complement.addAll(temp);  // 合并:周一、周二、周四、周五

5. 实际应用示例

5.1 权限管理系统

enum Permission {
    READ, WRITE, EXECUTE, DELETE, ADMIN
}
class User {
    private String name;
    private EnumSet<Permission> permissions;
    public User(String name, Permission... perms) {
        this.name = name;
        this.permissions = EnumSet.noneOf(Permission.class);
        this.permissions.addAll(Arrays.asList(perms));
    }
    public void addPermission(Permission perm) {
        permissions.add(perm);
    }
    public void removePermission(Permission perm) {
        permissions.remove(perm);
    }
    public boolean hasPermission(Permission perm) {
        return permissions.contains(perm);
    }
    public boolean hasAllPermissions(Permission... perms) {
        return permissions.containsAll(Arrays.asList(perms));
    }
    public boolean isAdmin() {
        return permissions.contains(Permission.ADMIN);
    }
    public EnumSet<Permission> getEffectivePermissions() {
        if (isAdmin()) {
            return EnumSet.allOf(Permission.class);
        }
        return permissions.clone();
    }
    // 使用示例
    public static void main(String[] args) {
        User user = new User("Alice", Permission.READ, Permission.WRITE);
        System.out.println("Can read? " + user.hasPermission(Permission.READ));
        System.out.println("Can delete? " + user.hasPermission(Permission.DELETE));
        user.addPermission(Permission.EXECUTE);
        System.out.println("Effective permissions: " + user.getEffectivePermissions());
    }
}

5.2 状态机实现

enum ProcessState {
    NEW, READY, RUNNING, BLOCKED, TERMINATED
}
enum Event {
    START, SCHEDULE, IO_REQUEST, IO_COMPLETE, TIME_OUT, EXIT
}
class ProcessStateMachine {
    private static final Map<ProcessState, EnumSet<Event>> VALID_TRANSITIONS = 
        Map.of(
            ProcessState.NEW, EnumSet.of(Event.START),
            ProcessState.READY, EnumSet.of(Event.SCHEDULE),
            ProcessState.RUNNING, EnumSet.of(Event.IO_REQUEST, Event.TIME_OUT, Event.EXIT),
            ProcessState.BLOCKED, EnumSet.of(Event.IO_COMPLETE),
            ProcessState.TERMINATED, EnumSet.noneOf(Event.class)
        );
    private ProcessState currentState = ProcessState.NEW;
    public boolean transition(Event event) {
        EnumSet<Event> validEvents = VALID_TRANSITIONS.get(currentState);
        if (validEvents.contains(event)) {
            currentState = getNextState(event);
            return true;
        }
        return false;
    }
    private ProcessState getNextState(Event event) {
        switch (event) {
            case START: return ProcessState.READY;
            case SCHEDULE: return ProcessState.RUNNING;
            case IO_REQUEST: return ProcessState.BLOCKED;
            case IO_COMPLETE: return ProcessState.READY;
            case TIME_OUT: return ProcessState.READY;
            case EXIT: return ProcessState.TERMINATED;
            default: throw new IllegalStateException("Invalid event");
        }
    }
}

5.3 配置选项管理

enum FeatureFlag {
    NEW_UI, DARK_MODE, AUTO_SAVE, ANALYTICS, 
    SOCIAL_SHARE, OFFLINE_MODE, PREMIUM_FEATURES
}
class AppConfig {
    private EnumSet<FeatureFlag> enabledFeatures = EnumSet.noneOf(FeatureFlag.class);
    private EnumSet<FeatureFlag> experimentalFeatures = EnumSet.noneOf(FeatureFlag.class);
    public void enableFeature(FeatureFlag feature) {
        enabledFeatures.add(feature);
    }
    public void disableFeature(FeatureFlag feature) {
        enabledFeatures.remove(feature);
    }
    public boolean isFeatureEnabled(FeatureFlag feature) {
        return enabledFeatures.contains(feature);
    }
    public void markAsExperimental(FeatureFlag feature) {
        experimentalFeatures.add(feature);
    }
    public EnumSet<FeatureFlag> getEnabledNonExperimentalFeatures() {
        EnumSet<FeatureFlag> result = EnumSet.copyOf(enabledFeatures);
        result.removeAll(experimentalFeatures);
        return result;
    }
    public EnumSet<FeatureFlag> getFeaturesForUser(boolean isPremiumUser) {
        EnumSet<FeatureFlag> features = EnumSet.copyOf(enabledFeatures);
        if (!isPremiumUser) {
            features.remove(FeatureFlag.PREMIUM_FEATURES);
        }
        return features;
    }
}

6. 性能特点

6.1 时间复杂度

  • add(), remove(), contains(): O(1)
  • 集合运算:O(n),n是枚举常量数量
  • 迭代:O(n)
  • 空间复杂度:O(1) 到 O(n/64)

6.2 性能对比

// EnumSet vs HashSet vs TreeSet
enum TestEnum { 
    A, B, C, D, E, F, G, H, I, J, 
    K, L, M, N, O, P, Q, R, S, T 
}
class PerformanceTest {
    public static void main(String[] args) {
        TestEnum[] values = TestEnum.values();
        int iterations = 1000000;
        // EnumSet
        EnumSet<TestEnum> enumSet = EnumSet.noneOf(TestEnum.class);
        long start = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            enumSet.add(values[i % values.length]);
            enumSet.contains(values[i % values.length]);
            enumSet.remove(values[i % values.length]);
        }
        long enumSetTime = System.nanoTime() - start;
        // HashSet
        Set<TestEnum> hashSet = new HashSet<>();
        start = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            hashSet.add(values[i % values.length]);
            hashSet.contains(values[i % values.length]);
            hashSet.remove(values[i % values.length]);
        }
        long hashSetTime = System.nanoTime() - start;
        System.out.println("EnumSet time: " + enumSetTime / 1_000_000 + "ms");
        System.out.println("HashSet time: " + hashSetTime / 1_000_000 + "ms");
    }
}

7. 与BitSet对比

特性EnumSetBitSet
元素类型枚举常量任意整数索引
类型安全强类型,编译时检查弱类型,运行时检查
性能更快,专门优化快,但不如EnumSet
内存更节省节省
可读性更高较低
扩展性固定,限于枚举常量动态扩展

8. 使用场景和最佳实践

8.1 适用场景

  1. 枚举集合操作:需要存储和操作枚举值集合
  2. 状态管理:系统状态、权限、标志位
  3. 配置管理:功能开关、选项集合
  4. 有限状态机:状态转换
  5. 高性能要求:需要最佳性能的集合操作

8.2 最佳实践

// 1. 使用静态工厂方法代替构造函数
// 好:
EnumSet<Day> days = EnumSet.of(Day.MONDAY, Day.TUESDAY);
// 不好:
// EnumSet<Day> days = new EnumSet<>();  // 没有public构造函数
// 2. 优先使用range()创建连续范围
EnumSet<Day> workWeek = EnumSet.range(Day.MONDAY, Day.FRIDAY);
// 3. 使用noneOf()创建空集合
EnumSet<Day> empty = EnumSet.noneOf(Day.class);
// 4. 利用clone()避免修改原集合
EnumSet<Day> original = EnumSet.of(Day.MONDAY, Day.TUESDAY);
EnumSet<Day> copy = original.clone();
copy.add(Day.WEDNESDAY);  // 不影响original
// 5. 与Collections工具类配合
EnumSet<Day> synchronizedSet = Collections.synchronizedSet(EnumSet.noneOf(Day.class));
EnumSet<Day> unmodifiableSet = Collections.unmodifiableSet(EnumSet.allOf(Day.class));
// 6. 合理使用complementOf()
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
EnumSet<Day> workdays = EnumSet.complementOf(weekend);  // 周一至周五

8.3 线程安全处理

// 方案1:使用Collections.synchronizedSet
class ThreadSafeEnumSet {
    private final Set<Permission> permissions = 
        Collections.synchronizedSet(EnumSet.noneOf(Permission.class));
    public void addPermission(Permission perm) {
        permissions.add(perm);
    }
    public boolean hasPermission(Permission perm) {
        return permissions.contains(perm);
    }
}
// 方案2:使用CopyOnWriteArraySet(适合读多写少)
class CopyOnWriteEnumSet {
    private final Set<Permission> permissions = 
        new CopyOnWriteArraySet<>(EnumSet.noneOf(Permission.class));
}
// 方案3:使用锁
class LockedEnumSet {
    private final Set<Permission> permissions = EnumSet.noneOf(Permission.class);
    private final Object lock = new Object();
    public void addPermission(Permission perm) {
        synchronized(lock) {
            permissions.add(perm);
        }
    }
}

9. 常见陷阱和注意事项

9.1 空值处理

// EnumSet不允许null元素
try {
    EnumSet<Day> set = EnumSet.of(Day.MONDAY);
    set.add(null);  // 抛出NullPointerException
} catch (NullPointerException e) {
    System.out.println("EnumSet不允许null元素");
}

9.2 类型安全

enum Color { RED, GREEN, BLUE }
enum Size { SMALL, MEDIUM, LARGE }
// 编译错误:类型不匹配
// EnumSet<Color> colors = EnumSet.of(Size.SMALL); 
// 正确
EnumSet<Color> colors = EnumSet.of(Color.RED, Color.GREEN);

9.3 性能考虑

// 避免频繁创建
class EfficientUsage {
    private static final EnumSet<Day> WEEKEND = 
        EnumSet.of(Day.SATURDAY, Day.SUNDAY);
    // 重用常量集合
    public boolean isWeekend(Day day) {
        return WEEKEND.contains(day);
    }
}

10. 高级用法

10.1 枚举常量分组

enum AppPermission {
    // 用户权限
    VIEW_PROFILE, EDIT_PROFILE, CHANGE_PASSWORD,
    // 管理员权限
    VIEW_USERS, EDIT_USERS, DELETE_USERS,
    // 系统权限
    BACKUP, RESTORE, CONFIG_CHANGE;
    // 分组
    public static final EnumSet<AppPermission> USER_PERMISSIONS = 
        EnumSet.of(VIEW_PROFILE, EDIT_PROFILE, CHANGE_PASSWORD);
    public static final EnumSet<AppPermission> ADMIN_PERMISSIONS = 
        EnumSet.of(VIEW_USERS, EDIT_USERS, DELETE_USERS);
    public static final EnumSet<AppPermission> SYSTEM_PERMISSIONS = 
        EnumSet.of(BACKUP, RESTORE, CONFIG_CHANGE);
    public static final EnumSet<AppPermission> ALL_PERMISSIONS = 
        EnumSet.allOf(AppPermission.class);
}

10.2 枚举集合运算工具类

class EnumSetUtils {
    // 安全的并集(不修改原集合)
    public static <E extends Enum<E>> EnumSet<E> union(EnumSet<E> set1, EnumSet<E> set2) {
        EnumSet<E> result = EnumSet.copyOf(set1);
        result.addAll(set2);
        return result;
    }
    // 安全的交集
    public static <E extends Enum<E>> EnumSet<E> intersection(EnumSet<E> set1, EnumSet<E> set2) {
        EnumSet<E> result = EnumSet.copyOf(set1);
        result.retainAll(set2);
        return result;
    }
    // 对称差
    public static <E extends Enum<E>> EnumSet<E> symmetricDifference(
            EnumSet<E> set1, EnumSet<E> set2) {
        EnumSet<E> union = union(set1, set2);
        EnumSet<E> intersection = intersection(set1, set2);
        union.removeAll(intersection);
        return union;
    }
    // 转换为位掩码
    public static <E extends Enum<E>> long toBitMask(EnumSet<E> set) {
        long mask = 0;
        for (E element : set) {
            mask |= 1L << element.ordinal();
        }
        return mask;
    }
    // 从位掩码恢复
    public static <E extends Enum<E>> EnumSet<E> fromBitMask(long mask, Class<E> enumClass) {
        EnumSet<E> result = EnumSet.noneOf(enumClass);
        E[] constants = enumClass.getEnumConstants();
        for (E constant : constants) {
            if ((mask & (1L << constant.ordinal())) != 0) {
                result.add(constant);
            }
        }
        return result;
    }
}

EnumSet是处理枚举集合的首选工具,它结合了类型安全、高性能和简洁的API,特别适合在需要高效处理枚举值集合的场景中使用。

到此这篇关于Java中的EnumSet使用实例详解的文章就介绍到这了,更多相关java enumset使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • maven打包报错:Non-resolvable parent POM for问题及解决

    maven打包报错:Non-resolvable parent POM for问题及解决

    本文详细解析了Maven父子项目编译打包时遇到的报错原因,指出在父项目标签中误添加了相对路径,导致子项目无法找到父项目的问题,并提供了解决方案,即移除相对路径标签,同时强调了正确配置的重要性
    2026-06-06
  • Java零基础精通方法篇

    Java零基础精通方法篇

    方法,也称函数,如果想要重复一段或者多段代码块的使用,可以将这些代码封装成一个方法,方法具体表现为某种行为,使用方法可以提高代码的复用性
    2022-05-05
  • Spring boot配置文件加解密详解

    Spring boot配置文件加解密详解

    这篇文章主要给大家介绍了关于Spring boot配置文件加解密的相关资料,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • Java 判断字符串中是否包含中文的实例详解

    Java 判断字符串中是否包含中文的实例详解

    这篇文章主要介绍了Java 判断字符串中是否包含中文的实例详解的相关资料,这里提供实例来说明该如何实现这样的功能,需要的朋友可以参考下
    2017-08-08
  • JAVA如何把数据库的数据处理成树形结构

    JAVA如何把数据库的数据处理成树形结构

    本文介绍了JAVA如何把数据库的数据处理成树形结构,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • java 二分法算法的实例

    java 二分法算法的实例

    这篇文章主要介绍了java 二分法算法的实例的相关资料,希望通过本文大家能够掌握二分法,需要的朋友可以参考下
    2017-09-09
  • Jvm sandbox mock机制的实践过程

    Jvm sandbox mock机制的实践过程

    这篇文章主要介绍了Jvm sandbox mock机制的实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • java堆排序原理及算法实现

    java堆排序原理及算法实现

    本篇文章主要介绍了堆排序的简介,定义,算法实现以及堆排序的性质。想要了解的朋友可以参考下
    2017-04-04
  • 浅谈@mapper引入不到引入的是@MapperScan的问题

    浅谈@mapper引入不到引入的是@MapperScan的问题

    这篇文章主要介绍了浅谈@mapper引入不到引入的是@MapperScan的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • JAVA监控JMX的使用

    JAVA监控JMX的使用

    Java Management Extensions(JMX)提供了一种标准化的方法来管理和监控Java应用程序,为Java应用提供了一种高效、一致的管理方式,本文就来介绍一下JMX的使用,感兴趣的可以了解一下
    2024-10-10

最新评论