基本的枚举定义
enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。
定义:
package top.twolovelypig;public enum EnumMain {MON, TUE, WED, THU, FRI, SAT, SUN;}
输出枚举值代码:
package top.twolovelypig;public class Test {public static void main(String[] args) {for (EnumMain e : EnumMain.values()) {System.out.println(e.toString());}}}
enum对象基本方法
int compareTo(E o)该方法用来比较枚举与指定对象的顺序public static void main(String[] args) {//值为6,表明SUN在MON后面六位System.out.println(EnumMain.SUN.compareTo(EnumMain.MON));//值为-2,表明tue比thu小两位(tue在thu前面两位)System.out.println(EnumMain.TUE.compareTo(EnumMain.THU));//值为0,表示二者是一样的System.out.println(EnumMain.MON.compareTo(EnumMain.MON));}
需要注意的是这里比较的值是有大小和正负的,不是说后面的与前面的相比结果就是1,也有可能是其他正数,具体结果是几就需要看后面的枚举是在前面的枚举后几位
Class<E> ``**getDeclaringClass**()返回与枚举常量的枚举类型相对应的class对象package top.twolovelypig;public class Test {public static void main(String[] args) {EnumMain enumMain = EnumMain.FRI;System.out.println("getDeclaringClass(): " + enumMain.getDeclaringClass().getName());}}
输出的结果是类的全路径:
getDeclaringClass(): top.twolovelypig.EnumMainString name()返回此枚举常量的名称public static void main(String[] args) {EnumMain enumMain = EnumMain.FRI;System.out.println("name(): " + enumMain.name());}
输出结果是:
name(): FRIint ordinal()返回枚举常量的序数(初始常量序数为0)public static void main(String[] args) {EnumMain enumMain = EnumMain.FRI;System.out.println("ordinal(): " + enumMain.ordinal());}
输出结果是4,因为
FRI是第五个,初始常量序数是0,所以输出结果是4String toString()返回枚举常量的名称
给enum自定义属性和方法(带参数的enum)
enum
package top.twolovelypig;public enum EnumMain {MON("星期一", 1),TUE("星期二", 2),WED("星期三", 3),THU("星期四", 4),FRI("星期五", 5),SAT("星期六", 6),SUN("星期天",7);// 成员变量private String name;private int index;// 构造方法private EnumMain(String name, int index) {this.name = name;this.index = index;}// 普通方法 根据index获取namepublic static String getNameByIndex(int index) {for (EnumMain c : EnumMain.values()) {if (c.getIndex() == index) {return c.name;}}return null;}// 普通方法 根据index获取namepublic static int getIndexByName(String name) {for (EnumMain c : EnumMain.values()) {if (c.name.equals(name)) {return c.index;}}return 0;}// get set 方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}}
上面代码中getIndexByName()方法中需要注意c.name与c.getName()的区别,c.name获取的是中文比如星期三,而c.getName()的结果是FRI。
测试代码,根据名称获取索引,根据索引获取名称等:
package top.twolovelypig;public class Test {public static void main(String[] args) {EnumMain enumMain = EnumMain.FRI;//普通get方法 输出结果是5System.out.println(enumMain.getIndex());//普通getName()方法 输出结果是星期五System.out.println(enumMain.getName());//根据index获取name 输出结果是星期三System.out.println(EnumMain.getNameByIndex(3));//根据name获取index 输出结果是3System.out.println(EnumMain.getIndexByName("星期三"));}}
对枚举的理解
可能不好理解的就是上面具有参数的枚举,其实只需要记住一点,java中一切皆对象,可以把枚举页当做一个类,这样来看的话上面的代码可以写成下面这样:
package top.twolovelypig;public class EnumMain {// 成员变量private String name;private int index;// 构造方法private EnumMain(String name, int index) {this.name = name;this.index = index;}// get set 方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}}
对于上面的类比较好理解吧,就是具有两个属性而已,然后呢就是一个私有构造方法以及get/set方法。而对于枚举中的这些声明
MON("星期一", 1),TUE("星期二", 2),WED("星期三", 3),THU("星期四", 4),FRI("星期五", 5),SAT("星期六", 6),SUN("星期天",7);
其实就是该枚举类的对象,每一个声明都是一个对象,也就是这里其实有七个对象,此时简单理解枚举与类的区别就是枚举中对象是数量固定,相当于在一开始就实例化了几个固定的对象而已。然后后面哪些根据key获取name,以及根据name获取key都是自己加的一些方法而已。
enumMap
以下内容来自《java编程的逻辑》这本书。
如果需要一个Map的实现类,并且建的类型为枚举类型,可以使用HashMap,但应该使用一个专门的实现类EnumMap。因为枚举类型有两个特征:
- 枚举所有可能的值时有限的并且是预定义的
- 所有的枚举值有一个顺序
这两个特征可以更为高效的实现Map接口。
案例
比如有一批关于衣服的记录,想要通过尺寸统计衣服的数量,定义一个简单的枚举类Size;都表示衣服的尺寸。
Size枚举:
public enum Size{SMALL, MEDIUM, LARGE}
Clothes类
class Clothes{String id;Size size;//get与set}
按尺寸统计数量:
public static Map<Size, Integer> countBySize(List<Clothes> clothes){Map<Size, Integer> map = new EnumMap(Size.class);for(Clothes c : clothes){Size size = c.getSize();Integer count = map.get(size);if(count != null){map.put(size, count+1);}else{map.put(size, 1);}}}
需要注意EnumMap的构造方法
Map<Size, Integer> map = new EnumMap(Size.class);
EnumMap需要传递一个类型信息,Size.class表示枚举类Size的运行时信息,需要这个参数是因为EnumMap要知道具体的枚举类是什么。
测试代码:
List<Clothes> clothes = Arrays.asList(new Clothes[]{new Clothes("c001", Size.SMALL),new Clothes("c002", Size.MEDIUM),new Clothes("c003", Size.LARGE),new Clothes("c004", Size.SMALL),new Clothes("c005", Size.MEDIUM),new Clothes("c006", Size.LARGE)});System.out.println(countBySize(clothes));
需要说明的是,EnumMap是保证顺序的,输出是按照键在枚举中的顺序的。
enum的另外两个构造方法
除了以上介绍的构造方法,EnumMap还有两个构造方法,可以接受一个键值匹配的EnumMap或普通Map,如下所示:
public EnumMap(EnumMap<K, ? extends V> m)public EnumMap(Map<K, ? extends V> m)
比如:
Map<Size,Integer> hashMap = new HashMap<>();hashMap.put(Size.LARGE, 2);hashMap.put(Size.SMALL, 1);Map<Size, Integer> enumMap = new EnumMap<>(hashMap);
