• 枚举详解之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内放置的元素不重复。

  • 相关阅读:
    Codeforces 1129D Isolation dp + 分块 (看题解)
    Codeforces 1129C Morse Code dp
    bzoj 4119 后缀数组 + 并查集
    Codeforces 204E Little Elephant and Strings 后缀数组 + 并查集
    HDU
    HDU 6125 Free from square dp (看题解)
    Codeforces 913F Strongly Connected Tournament dp(看题解)
    Codeforces 1187F Expected Square Beauty (看题解)
    读《大道至简》第五章有感
    第六周课后作业
  • 原文地址:https://www.cnblogs.com/treeshu/p/11013511.html
Copyright © 2020-2023  润新知