java enumset_Java中的EnumSet – RegularEnumSet与JumboEnumSet

java enumset

Java中的EnumSet是Set 接口的特殊实现,是在Java 1.5语言中首次引入Enum时在Java 1.5中添加的。 令人惊讶的是,在Java 1.5发布(2004年9月30日发布,代号为Tiger)的许多年之后,许多Java程序员仍然不知道所引入的几个好功能。 EnumSet 就是这样的示例之一,与其他 针对Enum常量的 Set 实现 相比,它确实非常有用并且提供了更高的性能 。 当我 博客上 讨论 Java中的EnumMap时, 我也想提及 EnumSet ,但找不到时间。 但是, 从我的一位读者那里 读到最近的一次采访采访中有关 如何用Java实现EnumSet的 问题 触发了这篇文章。 实际上,由于EnumSet的高性能和专门用于Enum常量的原因,它在Java访谈中变得越来越流行。 在本Java教程中,我们将讨论EnumSet对Java的含义,如何以 RegularEnumSet 和 JumboEnumSet 的形式实现它 ,最重要的是 何时在Java中使用EnumSet

什么是EnumSet

如前所述,它是Set接口的特殊实现,这意味着您可以将其传递给接受Set接口作为参数的方法。 EnumSet只能与Enum常量一起使用,这意味着您不能在EnumSet中存储任何其他对象。 EnumSet还为创建实例的Factory方法设计模式提供了一个很好的例子。

它通过将EnumSet声明为抽象类并使其具体实现RegularEnumSet和JumboEnumSet package-private来强制使用Factory方法 这意味着您既不能创建EnumSet的实例,也不能创建其任何实现。 如果您针对不同的需求提供了不同的Factory方法,则这种强制执行是好的。 EnumSet就在这里,您可以看到EnumSet.of(E ...)之类的方法 ,该方法创建提供给它的元素的EnumSet 。

这是 方法重载变量参数 的绝佳用法 。 EnumSet.of() 方法被重载以用于一般用途,它的性能往往优于可变参数版本,并且可以添加 EnumSet.of() 方法来灵活地创建具有任意数量实例的枚举。 此外 EnumSet 提供了像 copyOf 方法 (i),noneOf() 通过复制从其他集合的元素,和创建Java中的特定Enum类型的空EnumSet 创建 EnumSet。

如何用Java实现EnumSet

EnumSet是一个抽象类,它提供了两个具体的实现,即 java.util.RegularEnumSet和java.util.JumboEnumSet。 两者之间的主要区别在于,前者使用long变量来存储元素,而后者使用long []来存储其元素。 由于RegularEnumSet使用long变量(它是64位数据类型),因此只能容纳这么多的元素。 这就是为什么使用EnumSet.noneOf()方法创建一个空EnumSet的原因。 它选择RegularEnumSet如果键宇宙(在密钥枚举枚举实例数)小于或等于64。它选择JumboEnumSet如果键宇宙超过64.下面是其确实的代码:

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
     
        .. ............
        if (universe.length <= 64)
            return new RegularEnumSet<E>(elementType, universe);
        else
            return new JumboEnumSet<E>(elementType, universe);
    }

尽管从细节上讲这是一个非常低级的实现,但是如果被问到这个问题,在工作面试中留下深刻的印象总是很高兴的。

何时在Java中使用EnumSet

Joshua Bloch 在Java经典 有效Java的 项目32中提到了EnumSet的一个有趣的用例场景。 此项建议我们使用 EnumSet 代替位字段,它是enum int模式的一部分。 在 枚举int模式中 ,不同的枚举常量表示为2的幂,然后使用 位运算符进行 组合 。 我强烈建议您看书中提到的那个例子。 这非常清楚,也非常有用。 现在回到一般用法–每当出于有意义的目的需要将某些枚举分组时,都可以使用 EnumSet,例如,如果有一个枚举表示DayOfWeek ,则可以使用 EnumSet 创建 WEEKDAYS 和 WEEKEND ,而不是为该示例定义单独的枚举。 所以,

 

private enum DayOfWeek{

MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

}



private EnumSet weekend = EnumSet.of(SATURDAY,SUNDAY);

同样,一年中的月份可以按逻辑分组为不同的季节,例如 夏季 , 冬季 ,如下所示:

enum Month{

JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,

AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;

}



EnumSet summer = EnumSet.of(Month.MARCH, Month.APRIL, Month.MAY, Month.JUNE);



EnumSet winter = EnumSet.of(Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER, Month.JANUARY);

因此,除了在枚举int模式中 使用 EnumSet 之外 ,您还可以使用它为单个枚举类型的不同实例创建逻辑分组。

有关EnumSet的要点

以下是有关Java中EnumSet的一些有价值的知识。 像所有其他集合类一样,强烈建议 您在生产代码中使用 EnumSet 之前先 熟悉它的细节 。

  1. 只能创建一个枚举类型的EnumSet,这意味着您不能一起创建 Month和DayOfWeek的 EnumSet 。
  2. EnumSet不允许使用null元素。 尝试在 EnumSet 上插入null 会抛出 NullPointerException
  3. EnumSet 不是 线程安全的 ,这意味着当多个线程访问它并且其中一个修改集合时,是否需要对其进行外部同步。
  4. EnumSet的 迭代器是故障安全的和弱一致性的,这意味着没有ConcurrentModificationException 。 Iterator的遍历顺序也是由Enum的自然顺序定义的,它可能会或可能不会显示在迭代过程中进行的任何修改的结果。
  5. EnumSet是一个高性能的Java集合。 由于基于数组的访问, 它 为 add() , contains()和next()操作提供O(1)性能 。 最好在HashSet上使用EnumSet来存储Enum常量。

感谢您的宝贵时间,希望您能尽可能多地利用EnumSet。 您还应该阅读EnumSet上的Effective Java及其项目,以了解枚举int模式以及EnumSet如何替代它。


翻译自: https://jaxenter.com/enumset-in-java-regularenumset-vs-jumboenumset-106051.html

java enumset

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值