枚举详解之EnumSet、EnumMap用法

枚举简单例子
/**
 * @author shuliangzhao
 * @Title: Color
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/6/12 22:35
 */
public enum Color {

    YELLOW,
    RED,
    BLUE,
    PURPLE,
    BLACK;

}
/**
 * @author shuliangzhao
 * @Title: ColorEnumTest
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/6/12 22:37
 */
public class ColorEnumTest {

    public static void main(String[] args) {
        Color color = Color.BLUE;
        switch (color) {
            case RED:
                System.out.println("红色");
                break;
            case BLUE:
                System.out.println("蓝色");
                break;
            case PURPLE:
                System.out.println("紫色");
                break;
            case BLACK:
                System.out.println("黑色");
                break;
            case YELLOW:
                System.out.println("黄色");
                break;
             default:
                 System.out.println("蓝色");
                 break;
        }
    }

}

测试结果


image.png

Color枚举的本质就是一个类,编译器会自动为我们生成Color类,通过反编译得到该类如下:

final class Color extends Enum {
    //编译器为我们添加的静态的values()方法
    public static Color[] values()
    {
        return (Color[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Color valueOf(String s)
    {
        return (Color)Enum.valueOf(com/sl/emun/Color, s);
    }
    //私有构造函数
    private Color(String s, int i)
    {
        super(s, i);
    }
    //前面定义的7种枚举实例
    public static final Color YELLOW;
    public static final Color RED;
    public static final Color BLUE;
    public static final Color PURPLE;
    public static final Color BLACK;
    private static final Color $VALUES[];

    static
    {
        //实例化枚举实例
        YELLOW = new Color("YELLOW", 0);
        RED = new Color("RED", 1);
        BLUE = new Color("BLUE", 2);
        PURPLE = new Color("PURPLE", 3);
        BLACK = new Color("BLACK", 4);
        $VALUES = (new Color[] {
                YELLOW, RED, BLUE, PURPLE, BLACK
        });
    }
}

可以看出每个枚举类型颜色是该Color类的一个实例对象,该构成方式和单例模式有些类似,故可以用只有一个枚举类型的枚举作为单例模式,而且枚举的构造器由编译器管理安全性十分高,既可以防止反射破解也可以防止反序列破解。

EnumMap用法
/**
 * @author shuliangzhao
 * @Title: EnumMapTest
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/6/12 22:49
 */
public class EnumMapTest {

    public static void main(String[] args) {
        EnumMap<Color,String> enumMap = new EnumMap(Color.class);
        enumMap.put(Color.BLACK,"黑色");
        enumMap.put(Color.BLUE,"蓝色");
        System.out.println(enumMap);
        System.out.println(enumMap.get(Color.BLUE));
    }
}

运行结果


image.png

EnumMap put方法

public V put(K key, V value) {
        typeCheck(key);

        int index = key.ordinal();
        Object oldValue = vals[index];
        vals[index] = maskNull(value);
        if (oldValue == null)
            size++;
        return unmaskNull(oldValue);
    }

首先调用typeCheck检查键的类型,如果类型不对,会抛出异常。类型正确的话,调用ordinal获取索引index,并将值value放入值数组vals[index]中。EnumMap允许值为null,为了区别null值与没有值,EnumMap将null值包装成了一个特殊的对象,有两个辅助方法用于null的打包和解包,打包方法为maskNull,解包方法为unmaskNull。

get方法

public V get(Object key) {
        return (isValidKey(key) ?
                unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
    }

键有效的话,通过ordinal方法取索引,然后直接在值数组vals里找。isValidKey的代码与typeCheck类似,但是返回boolean值而不是抛出异常。

以上就是EnumMap的基本实现原理,内部有两个数组,长度相同,一个表示所有的键,一个表示对应的值,值为null表示没有该键值对,键都有一个对应的索引,根据索引可直接访问和操作其键和值,效率很高。

EnumSet

EnumSet这是一个用来操作Enum的集合,是一个抽象类,它有两个继承类:JumboEnumSet和RegularEnumSet。在使用的时候,需要确定枚举类型。它的特点也是速度非常快,为什么速度很快呢?因为每次add的时候,每个枚举值只占一个长整型的一位。
EnumSet.noneOf()方法创建一个空的set

public class EnumSetTest {

    public static void main(String[] args) {
        EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);
    }
}

运行结果


image.png

EnumSet.allOf()方法创建一个满的set

/**
 * @author shuliangzhao
 * @Title: EnumSetTest
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/6/12 23:24
 */
public class EnumSetTest {

    public static void main(String[] args) {
        /*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);*/
        EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
        System.out.println(enumSet);
    }
}

运行结果


image.png

EnumSet.range创建指定范围set

public class EnumSetTest {

    public static void main(String[] args) {
        /*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
        System.out.println(enumSet);*/
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
    }
}
image.png

EnumSet.complementOf补集创建set

public class EnumSetTest {

    public static void main(String[] args) {
        /*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
        System.out.println(enumSet);*/
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
        System.out.println(enumSet1);
    }
}

运行结果


image.png

EnumSet.copyOf复制创建set

public class EnumSetTest {

    public static void main(String[] args) {
        /*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
        System.out.println(enumSet1);*/
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet1 = EnumSet.copyOf(enumSet);
        System.out.println(enumSet1);
    }
}

运行结果


image.png

EnumSet.copyOf复制创建集合

public class EnumSetTest {

    public static void main(String[] args) {
        /*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
        System.out.println(enumSet);
        enumSet.add(Color.BLUE);
        enumSet.add(Color.PURPLE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
        System.out.println(enumSet);
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
        System.out.println(enumSet1);
        EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
        System.out.println(enumSet);
        EnumSet<Color> enumSet1 = EnumSet.copyOf(enumSet);
        System.out.println(enumSet1);*/
        List<Color> colors = new ArrayList<>();
        colors.add(Color.PURPLE);
        colors.add(Color.BLUE);
        colors.add(Color.BLUE);
        System.out.println(colors);
        EnumSet<Color> enumSet = EnumSet.copyOf(colors);
        System.out.println(enumSet);
    }
}

运行结果


image.png

注意:通过结果可以看出ArrayList内放置的元素可以重复,而EnumSet内放置的元素不重复。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 18.7.18一、概述枚举常量在类型安全性和便捷性都很有保证,如果出现类型问题编译器也会提示我们改进。除了不能继承...
    静心安分读书阅读 519评论 0 0
  • Chapter 6 Enums and Annotations 枚举和注解 JAVA supports two s...
    LaMole阅读 777评论 0 2
  • Java集合类可用于存储数量不等的对象,并可以实现常用的数据结构如栈,队列等,Java集合还可以用于保存具有映射关...
    小徐andorid阅读 1,898评论 0 13
  • 枚举和注解是Java1.5版本中新增的特性,本章讨论使用它们时的最佳实践。本章内容导图: 1.用enum代替int...
    塞外的风阅读 900评论 0 0
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,707评论 2 9