java枚举类型及枚举集合

一、枚举类型

/**
 * @author zhangys
 * @description
 * @date 2020/4/15
 */
public class EnumTest {

    enum Day {
        SUNDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
    }

    public static void main(String[] args) {
        System.out.println(Day.SUNDAY);
        System.out.println(TestEnum.VALUE1);
    }
}


enum TestEnum {
    VALUE1, VALUE2
}

//输出
SUNDAY
VALUE1

二、switch 操作

enum 支持 switch 操作。

/**
 * @author zhangys
 * @description
 * @date 2020/4/15
 */
public class EnumTest {

    enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
    }

    public static void main(String[] args) {
        Day today = Day.WEDNESDAY;
        switch (today) {
            case MONDAY:
                System.out.println(Day.MONDAY);
                break;
            case TUESDAY:
                System.out.println(Day.TUESDAY);
                break;
            case WEDNESDAY:
                System.out.println(Day.WEDNESDAY);
                break;
            case THURSDAY:
                System.out.println(Day.THURSDAY);
                break;
            case FRIDAY:
                System.out.println(Day.FRIDAY);
                break;
            case SATURDAY:
                System.out.println(Day.SATURDAY);
                break;
            case SUNDAY:
                System.out.println(Day.SUNDAY);
                break;
        }

    }
}


//enum TestEnum {
//    VALUE1, VALUE2
//}

三、自定义枚举类

可以通过定制 Enum 类型来定义自己的枚举类。需要注意的是枚举类型的构造函数是私有的 private,所以不能通过 New 来创建枚举类型,正因如此才保证了枚举数据类型的安全,不会被更改。如:定义一个 Day enum 类型:

/**
 * @author zhangys
 * @date 2020/4/15
 */
public enum Day {

    SUNDAY(7, "周日"), MONDAY(1, "周一"), TUESDAY(2, "周二"),
    WEDNESDAY(3, "周三"), THURSDAY(4, "周四"), FRIDAY(5, "周五"),
    SATURDAY(6, "周六");

    private Integer code;
    private String name;


    Day(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

    ;

    public Integer getCode() {
        return code;
    }

    public String getName() {
        return name;
    }
}

测试

/**
 * @author zhangys
 * @description
 * @date 2020/4/15
 */
public class EnumTest {


    public static void main(String[] args) {
        Day today = Day.WEDNESDAY;
        switch (today) {
            case MONDAY:
                System.out.println(Day.MONDAY.getName());
                break;
            case TUESDAY:
                System.out.println(Day.TUESDAY.getName());
                break;
            case WEDNESDAY:
                System.out.println(Day.WEDNESDAY.getName());
                break;
            case THURSDAY:
                System.out.println(Day.THURSDAY.getName());
                break;
            case FRIDAY:
                System.out.println(Day.FRIDAY.getName());
                break;
            case SATURDAY:
                System.out.println(Day.SATURDAY.getName());
                break;
            case SUNDAY:
                System.out.println(Day.SUNDAY.getName());
                break;
        }

    }
}

//结果
周三

四、相关枚举类

4.1 EnumMap 枚举型映射/字典

EnumMap 是对 Map 接口的实现类,其 key-value 映射中的 key 是 Enum 类型,其原理是一个对象数组,数组的下标索引就是根据 Map 中的 key 直接获取(即枚举中的 ordinal 值),数组长度就是枚举类成员个数;当 key 为枚举类型时其效率比 HashMap 高,因为可以直接获取数组下标索引访问到元素;此外 EnumMap 是保证顺序的,输出是按照 key 在枚举中的顺序来确定的。

EnumMap 的构造方法

//需要传递一个类型信息,因为没有这个类信息就不知道具体的枚举类是什么,
// 也就无法初始化内部的数据结构。
        public EnumMap(Class < K > keyType)
// 其他构造方法。
        public EnumMap(EnumMap < K, ? extends V > m ) 
        public EnumMap(Map < K, ? extends V > m )

EnumMap 的实现原理

EnumMap 的实现原理依赖内部两个长度相同的数组,一个表示所有可能的键,一个表示对应的值,当放入 key-value 时首先会检查键的类型,如果类型不对会抛出异常,否则调用 key 的 ordinal 获取索引 index,并将值 value 放入值数组 vals[index] 中(注意:如果值 value 为 null,则为了区别真正的 null 与没有值,EnumMap 会将 null 值包装成一个特殊的对象)。

其构造方法主要就是在初始化相关数组,如下:

        public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements java.io.Serializable, Cloneable {
            //key键的具体枚举类型
            private final Class<K> keyType;
            // key的所有枚举值
            private transient K[] keyUniverse;
            // EnumMap的存储实现,仅仅为一个枚举成员个数长度的数组 
            private transient Object[] vals;

            ......

            // 构造方法
            public EnumMap(Class<K> keyType) {
                // key的枚举类型赋值
                this.keyType = keyType;
                // 获取枚举类的所有枚举值存入数组缓存使用
                keyUniverse = getKeyUniverse(keyType);
                // 实例化枚举值个数长度的数组 
                vals = new Object[keyUniverse.length];
            }
             ......
        }

测试

import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangys
 * @description
 * @date 2020/4/15
 */
public class EnumMapTest {
    public static void main(String[] args) {
        EnumMap<Day,String> enumMap = new EnumMap<Day, String>(Day.class);
        enumMap.put(Day.WEDNESDAY,"今天是周三");
        Map<Day,String> map = new HashMap<>();
        map.put(Day.WEDNESDAY,"今天是周三");
        System.out.println("enumMap:"+enumMap.get(Day.WEDNESDAY));
        System.out.println("map:"+map.get(Day.WEDNESDAY));
    }
}

4.2 EnumSet 枚举集合

EnumSet 是个抽象类,不能实例化,查看源码发现有提供静态实例化 JumboEnumSet 或 RegularEnumSet 对象的方法。这两个对象继承自 EnumSet,区别在于 EnumSet 大小,大于 64 时创建的是 JumboEnumSet 对象,小于 64 时创建的是 RegularEnumSet 对象。

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangys
 * @description
 * @date 2020/4/15
 */
public class EnumMapTest {
    public static void main(String[] args) {
        EnumSet<Day> enumSet = EnumSet.noneOf(Day.class);
        enumSet.add(Day.WEDNESDAY);
        enumSet.add(Day.MONDAY);
        System.out.println(enumSet.toString());
        for (Day day:enumSet){
            System.out.println("code:" + day.getCode()+"name:"+day.getName());
        }
        enumSet.clear();
        System.out.println(enumSet);
    }
}

//输出
[MONDAY, WEDNESDAY]
code:1name:周一
code:3name:周三
[]

EnumSet 是非线程安全的,要想线程安全使用 Collections.synchronizedSet() 处理 numSet 对象,如:

Set<Day> enumSet = Collections.synchronizedSet(EnumSet.noneOf(Day.class));
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值