秒懂系列,超详细Java枚举教程!!!

全部知识体系文章,GitHub已收录,欢迎Star!再次感谢,愿你早日进入大厂!java

GitHub地址: https://github.com/Ziphtracks/JavaLearningmanualgit

深刻理解Java枚举


1、什么是枚举

1.1 什么是枚举?

至于枚举,咱们先拿生活中的枚举来入手,而后再引伸Java中的枚举,其实它们的意义很类似。github

谈到生活中的枚举,假如咱们在玩掷骰子的游戏,在咱们手中有两个骰子,要求掷出两个骰子的点数和必须大于6的几率,那么在此情此景,咱们就须要使用枚举法一一列举出骰子点数的全部可能,而后根据列举出来的可能,求出几率。web

可能有的小伙伴发现,这就是数学啊?这就是数学中的几率学和统计学。对,咱们的枚举法就是经常使用于几率统计中的。spring

1.2 Java中的枚举类

Java 5.0引入了枚举,枚举限制变量只能是预先设定好的值。使用枚举能够减小代码中的 bug,方便不少场景使用。设计模式

2、Java枚举的语法

枚举类中的声明 数组

1访问修辞符 enum 枚举名 {
2    枚举成员,
3    枚举成员,
4    ...
5};

class类中枚举的声明 微信

1访问修饰符 class 类名 {
2    enum 枚举名 {
3        枚举成员,
4        枚举成员,
5        ...
6    }
7}

3、Java枚举类的使用规则和应用场景

3.1 Java枚举类的使用规则

至于枚举你也有所了解了,Java中的枚举也是同样的。而Java中枚举类的使用,也有特定的规则和场景。若是你看了如下的规则不明白的话,没有关系,继续向下学你就会明白,由于我在下面都会有讲解到这些规则。以下几个规则:app

  • 类的对象是肯定的有限个数。
  • 当须要定义一组常量时,建议使用枚举。
  • 若是枚举类中只有一个对象,则能够做为单例模式的实现方法。
  • 枚举类不能被继承
  • 枚举类不能被单独的new建立对象
  • 枚举类中的枚举成员是用`,`隔开的,多个枚举成员之间用`_`隔开
  • 若是枚举类中的只有一个或多个枚举成员,其余什么都没有,咱们在用`,`隔开的同时。最后能够省略`;`结束符。

注意: 若是关于枚举单例设计模式不太了解的小伙伴能够参考深度学习单例设计模式一文,你确定会有意想不到收获,请相信我!ide

3.2 Java枚举类的应用场景

根据Java中使用枚举类的规则,有如下几种场景适合来使用枚举类,以下:

  • 星期: Monday(星期一)、Tuesday(星期二)、Wednesday(星期三)、Thursday(星期四)、Firday(星期五)、Saturday(星期六)、Sunday(星期日)
  • 性别: Man(男)、Woman(女)
  • 季节: Spring(春天)、Summer(夏天)、Autumn(秋天)、Winter(冬天)
  • 支付方式: Cash(现金)、WeChatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、CreditCard(信用卡)
  • 订单状态: Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配货)、Delivered(已发货)、Return(退货)、Checked(已确认)
  • 线程状态: Establish(建立)、Ready(就绪)、Run(运行)、Obstruct(阻塞)、Die(死亡)
  • 等等……

4、枚举类的基本使用步骤解析

那咱们就解释如下这两个规则,咱们在上述中已经了解了枚举的做用。Java中枚举也不例外,也是一一列举出来方便咱们拿出来一个或多个使用。这有点像咱们的多选框,咱们把须要用到的全部选项内容放在各个多选框后面,当咱们在使用的时候只须要勾选本身须要的勾选框便可,这就表明了咱们须要被选中多选框后面的内容。

那么,Java中的枚举类是如何使用呢?

这里咱们简单的模拟一个场景,假设你的女友十分的喜欢喝点冷饮或热奶茶之类的饮品,在生活中也有不少像蜜雪冰城等等这种类型的饮品店。当你为女友买她爱喝的珍珠奶茶时,服务员会问你,要大杯、中杯仍是小杯的。固然,为了知足女友,你一般会选择大杯。这就意味着店内不容许顾客点规则外的饮品。

注意: 若是你是初学者或是不了解枚举类的使用,此基本使用不懂没有关系,请继续往下看便可!

因而,我用Java代码来实现一下,上述场景。

首先,建立枚举类。分别为珍珠奶茶添加大、中、小杯杯型。

 1package com.mylifes1110.java;
2
3/**
4 * @ClassName PearlMilkTea
5 * @Description 为珍珠奶茶添加三个杯型:大、中、小
6 * @Author Ziph
7 * @Date 2020/6/8
8 * @Since 1.8
9 */

10public enum PearlMilkTea {
11    //注意:这里枚举类中只有枚举成员,我在此省略了;结束符
12    SMALL, MEDIUM, LARGE
13}

其次,建立珍珠奶茶对象,再有方法来判断枚举类中的大、中、小杯。最后打印女友喝哪一个杯型的珍珠奶茶!

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.PearlMilkTea;
4
5/**
6 * @ClassName PearlMilkTeaTest
7 * @Description 为女友买哪一个杯型的珍珠奶茶(默认大杯)
8 * @Author Ziph
9 * @Date 2020/6/8
10 * @Since 1.8
11 */

12public class PearlMilkTeaTest {
13    public static void main(String[] args) {
14        //建立大杯的珍珠奶茶对象
15        PearlMilkTea pearlMilkTea = PearlMilkTea.LARGE;
16        PearlMilkTeaTest.drinkSize(pearlMilkTea);
17    }
18
19    //判断为女友买哪一个杯型的珍珠奶茶
20    public static void drinkSize(PearlMilkTea pearlMilkTea) {
21        if (pearlMilkTea == PearlMilkTea.LARGE) {
22            System.out.println("我为女友买了一大杯珍珠奶茶!");
23        } else if (pearlMilkTea == PearlMilkTea.MEDIUM) {
24            System.out.println("我为女友买了一中杯珍珠奶茶!");
25        } else {
26            System.out.println("我为女友买了一小杯珍珠奶茶!");
27        }
28    }
29}
image-20200608151052517
image-20200608151052517

虽然,咱们了解了枚举类中的基本使用,可是咱们在语法中还介绍了一种在类中定义的枚举。正好,在此也演示一下。以下:

1public class PearlMilkTea {
2    enum DrinkSize {
3        SMALL,
4        MEDIUM, 
5        LARGE
6    }
7}

若是这样建立就能够在class类中去建立enum枚举类了。想一想前面例子中的代码其实并不合理,这是为何呢?由于咱们写代码要遵循单一职责原则和见命知意的命名规范。因此,我写的代码是在珍珠奶茶的枚举类中列举的大、中、小的三种杯型枚举成员。因此根据规范来说,咱们珍珠奶茶中不能拥有杯型相关的枚举,毕竟咱们在生活中的这类饮品店中喝的全部饮品种类都有这三种杯型,所以咱们的全部饮品种类中都须要写一个枚举类,显然这是很不合理的。

若是让它变的更加合理化,咱们就细分饮品种类来建立饮品枚举类和杯型的枚举类并分别两两适用便可。也许有小伙伴会问我为何我要说这些合理不合理呢?由于自我感受这是对枚举类应用的思想铺垫,因此你品、你细品!

5、自定义枚举类

5.1 自定义枚举类步骤

关于第四章枚举类的基本使用,也许小伙伴们对枚举的陌生,而并不知道为何这样去建立枚举对象。接下来,我来带你使用常量来自定义枚举类,试试是否是那个效果。

既然,上述第三章我举出了这么多枚举类的应用场景,那咱们挑选一个比较经典的春夏秋冬来实现自定义枚举类。

首先,咱们先建立一个季节类,分别提供属性、私有构造器、春夏秋冬常量、Getter方法和toString方法,步骤以下:

 1package com.mylifes1110.java;
2
3/**
4 * 自定义季节的枚举类
5 */

6public class Season {
7    //声明Season对象的属性,为private final修饰
8    private final String seasonName;
9
10    //私有化构造器,并为对象赋值
11    private Season(String seasonName) {
12        this.seasonName = seasonName;
13    }
14
15    //提供当前枚举的多个对象,为public static final修饰
16    public static final Season SPRING = new Season("春天");
17    public static final Season SUMMER = new Season("夏天");
18    public static final Season AUTUMN = new Season("秋天");
19    public static final Season WINTER = new Season("冬天");
20
21    //提供外界经过getter方法来获取枚举对象的属性
22    public String getSeasonName() {
23        return seasonName;
24    }
25
26    //重写toString方法,以便打印出枚举结果
27    @Override
28    public String toString() {
29        return "Season{" +
30                "seasonName='" + seasonName + '\'' +
31                '}';
32    }
33}

其次,咱们去建立一个测试类,来使用该自定义枚举类建立对象。由此看来,咱们就能够根据类名来句点出常量对象了!

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.Season;
4
5/**
6 * 测试类
7 */

8public class SeasonTest {
9    public static void main(String[] args) {
10        Season spring = Season.SPRING;
11        System.out.println(spring);
12    }
13}

最后打印结果是春天的对象,因为咱们覆盖了toString方法,便可见对象内的内容。

image-20200608160220000
image-20200608160220000

5.2 使用带有参枚举类

若是你在第三章时Java枚举类的基本使用不明白,估计看完自定义枚举类也了解的大差不差了。可是你有没有发现咱们自定义枚举类是使用的有参数的对象呢?那咱们怎样使用真正的枚举类来实现有参数的枚举类呢?继续看吧那就!

在这里我将自定义枚举类改装了一下,改装成了enum枚举类实现的使用有参对象。以下:

 1package com.mylifes1110.java;
2
3public enum Season {
4    SPRING("春天"),
5    SUMMER("夏天"),
6    AUTUMN("秋天"),
7    WINTER("冬天");
8
9    private final String seasonName;
10
11    Season1(String seasonName) {
12        this.seasonName = seasonName;
13    }
14
15    public String getSeasonName() {
16        return seasonName;
17    }
18}

不知道你有没有发现少了点什么,少的部分其实就是咱们建立常量对象的部分,并且在这个枚举类中我也没有去重写toString方法,至于为何,下面就告诉你。

注意: 枚举对象之间用,隔开!

其次,去建立了该枚举类的测试类,咱们测试如下,并看一下没有重写toString方法打印出来的结果。

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.Season;
4
5public class Seaso1Test {
6    public static void main(String[] args) {
7        Season1 spring = Season.SPRING;
8        System.out.println(spring);                     //SPRING
9        System.out.println(spring.getSeasonName());     //春天
10    }
11}

这里我将打印的结果放在了打印语句后面的注释中。咱们发现没有重写toString方法居然打印出来的是SPRING,这是为何呢?这应该从咱们的继承关系中分析,若是继承的是基类Object的话,没有重写toString方法会打印对象地址。那么咱们就能够判定,enum枚举类的父类不是Object。那它的父类是谁呢?咱们能够借助来对象来获取其父类,以下:

1System.out.println(Season.class.getSuperclass());        //class java.lang.Enum

一样,答案放在了代码后面的注释中。咱们发现它默认继承的是Enum类。那么,咱们稍后就来就看看这个类中到底写了些什么方法。

6、Enum经常使用方法的使用

6.1 Enum中的全部方法

关于Enum类中的全部方法我以表格的方式列举出来!

返回值 方法 描述
String name() 获取枚举成员的名称
static T valueOf(Class<T> enumType, String name) 获取指定枚举成员名称和类型的枚举成员
String[] values() 获取枚举成员的全部值
int compareTo(E o) 比较此枚举与指定对象的顺序
int hashCode() 获取枚举成员的哈希值
int ordinal() 获取枚举成员的序数(第一个枚举成员位置为0)
String toString() 返回枚举成员名称
Class<E> getDeclaringClass() 获取枚举成员的类对象

6.2 name和toString

关于name方法和toString方法,其实很简单。name()就是根据枚举成员来获取该枚举成员的字符串名称。而同String方法也是用来获取枚举成员的字符串名称。虽然做用都是相同的,可是name方法是用final修饰的不能被重写,而toString是能够被重写的。这里咱们还使用季节的案例来演示,打印结果并放在了代码后面的注释中,以下:

1System.out.println(Season.SUMMER.name());            //SUMMER
2System.out.println(Season.SUMMER.toString());        //SUMMER

6.3 valueOf

此方法的做用是传入一个字符串,而后将它转换成对应的枚举成员。这里传入的字符串必须与定义的枚举成员的名称一致,严格区分大小写。若是传入的字符串并无找到其对应的枚举成员对象,就会抛出异常。以下:

1System.out.println(Season.valueOf("WINTER"));            //WINTER
2System.out.println(Season.valueOf("WIN"));                //java.lang.IllegalArgumentException
image-20200608173858862
image-20200608173858862

6.4 values

values方法的名字中就带有一个s,再加上它的返回值是一个字符串数组。因此咱们就能够得出它的做用是获取枚举成员的全部值,这些值并以数组的形式存储。

1Season[] seasons = Season.values();
2for (Season season : seasons) {
3    System.out.print(season + " ");
4}

结果为:

1SPRING SUMMER AUTUMN WINTER 

6.5 ordinal

该方法是获取枚举成员的序数,其第一个枚举成员位置为0。其实,为了好理解的话,能够把它看做数组中的索引。数组中的第一个元素位置一样也是从0开始。那咱们打印一下,看看结果如何,以下:

1//获取指定枚举成员的次序
2System.out.println(Season.SUMMER.ordinal());
3
4//获取全部成员的次序
5Season[] seasons = Season.values();
6for (Season s : seasons) {
7    System.out.println(s + " -> " + s.ordinal());
8}

结果为:

image-20200608175529079
image-20200608175529079

其源码就是返回了一个从0开始int类型的值,从源码中也能够看出最大值是int取值范围的最大值。以下:

image-20200608180839568
image-20200608180839568

6.6 compareTo

compareTo方法相信咱们已是很熟悉了。其做用就是用来比较的。可是在枚举类中它比较的是什么呢?实际上compareTo方法比较的是两个枚举成员的次序数,并返回次序相减后的结果。

首先,咱们要知道SUMMER的次序数为1,WINTER的次序数为3。当使用前者比较后者,打印的结果是前者与后者相减后的差值,即1-3=-2

1System.out.println(Season.SUMMER.compareTo(Season.WINTER));            //-2

它的源码是怎么作的呢?那咱们进入查看一下。

其中,前面的操做都是在判断比较的双方是不是一个枚举类,若是不是的话就抛出异常。若是为枚举类的话,就直接将次序数作了相减操做并返回。

image-20200608180532795
image-20200608180532795

7、Java枚举的高级特性

7.1 常量

咱们知道,常量是用public static final修饰的。1.5以后有了枚举,咱们就能够把相关的常量放在一个枚举容器中,并且使用枚举的好处还在于枚举为咱们提供了不少便捷的的方法。

示例:

1public enum Season {
2    SPRING, SUMMER, AUTUMN, WINTER
3}

7.2 switch语句

你了解的switch语句都支持哪一种类型呢?我这里说一下,switch语句支持的类型有以下几种:

  • 基本数据类型: byte、short、char、int
  • 包装数据类型: Byte、Short、Character、Integer
  • 枚举类型: Enum
  • 字符串类型: String(jdk7+ 开始支持)

具体枚举类与switch语句的使用是如何实现呢?枚举又是如何为switch语句提供便利的呢?来看一下吧。

 1package com.mylifes1110.java;
2
3public class WeekTest {
4    public static void main(String[] args) {
5        Week week = Week.MONDAY;
6        switch (week) {
7            case MONDAY:
8                System.out.println("星期一");
9                break;
10            case TUESDAY:
11                System.out.println("星期二");
12                break;
13            case WEDNESDAY:
14                System.out.println("星期三");
15                break;
16            case THURSDAY:
17                System.out.println("星期四");
18                break;
19            case FRIDAY:
20                System.out.println("星期五");
21                break;
22            case SATURDAY:
23                System.out.println("星期六");
24                break;
25            case SUNDAY:
26                System.out.println("星期日");
27                break;
28            default:
29                System.out.println("null");
30        }
31    }
32}
33
34enum Week {
35    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
36}

7.3 枚举中定义多个参数与方法

有参枚举在5.2中我已经作了详细说明,咱们在定义枚举时不仅是能够定义多个参数,还能够定义其余的普通方法来使用,而关于普通方法的使用是根据场景的,这里我就再也不作过多的赘述了。

 1package com.mylifes1110.java;
2
3public enum Season {
4    SPRING("春天"),
5    SUMMER("夏天"),
6    AUTUMN("秋天"),
7    WINTER("冬天");
8
9    private final String seasonName;
10
11    public static String getName(int index) {  
12        for (Season s : Season.values()) {  
13            if (c.getIndex() == index) {  
14                return c.name;  
15            }  
16        }  
17        return null;  
18    }
19
20    Season1(String seasonName) {
21        this.seasonName = seasonName;
22    }
23
24    public String getSeasonName() {
25        return seasonName;
26    }
27}

7.4 枚举类实现接口

虽然枚举类不能继承,可是能够实现接口。如下是一个实现过程。

首先,建立一个接口。

1package com.mylifes1110.inter;
2
3public interface Show {
4    void show();
5}

其次,让咱们的四季枚举类实现该接口并重写方法。

 1package com.mylifes1110.java;
2
3import com.mylifes1110.inter.Show;
4
5public enum Season implements Show {
6    SPRING("春天"),
7    SUMMER("夏天"),
8    AUTUMN("秋天"),
9    WINTER("冬天");
10
11    private final String seasonName;
12
13    Season1(String seasonName) {
14        this.seasonName = seasonName;
15    }
16
17    public String getSeasonName() {
18        return seasonName;
19    }
20
21    @Override
22    public void show() {
23        System.out.println("向往四季如春");
24    }
25}

最后,当咱们使用每个枚举类均可以调用show方法,而打印的结果也都是“向往四季如春”

1Season.WINTER.show();                //向往四季如春

聪明的你我相信发现了这个缺点,咱们无论使用哪个枚举成员时,调用的show方法都是同一个。因此,咱们在实现接口后,能够这样重写方法,以下:

 1package com.mylifes1110.java;
2
3import com.mylifes1110.inter.Show;
4
5public enum Season1 implements Show {
6    SPRING("春天") {
7        @Override
8        public void show() {
9            System.out.println("春天是个踏青的季节");
10        }
11    },
12    SUMMER("夏天") {
13        @Override
14        public void show() {
15            System.out.println("夏天是个炎热的季节,我要吃冰棍");
16        }
17    },
18    AUTUMN("秋天") {
19        @Override
20        public void show() {
21            System.out.println("秋天还算是凉爽");
22        }
23    },
24    WINTER("冬天") {
25        @Override
26        public void show() {
27            System.out.println("冬天的雪还不错,就是有点冷");
28        }
29    };
30
31    private final String seasonName;
32
33    Season1(String seasonName) {
34        this.seasonName = seasonName;
35    }
36
37    public String getSeasonName() {
38        return seasonName;
39    }
40}

咱们在枚举成员的后面加了{},而重写的方法能够写在各个枚举成员中,这样就接触了上述全部的那个限制。这下,咱们使用哪一个枚举成员对象调用show方法都是不一样的。是否是很是NICE?

7.5 使用接口对枚举分类

使用接口对枚举分类,咱们须要建立一个接口容器,里面存放着此接口容器所存放的多个枚举类,而后将各个枚举类实现此接口,以这样的方式可实现对枚举分类。代码以下,打印结果放在了代码后面的注释中:

 1package com.mylifes1110.inter;
2
3public interface Weeks {
4    //工做日
5    enum WorkingDay implements Weeks {
6        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
7    }
8
9    //双休日
10    enum Weekend implements Weeks {
11        SATURDAY, SUNDAY
12    }
13}
14
15class WeeksTest {
16    public static void main(String[] args) {
17        System.out.print("双休日:");
18        for (Weeks.Weekend weekend : Weeks.Weekend.values()) {
19            System.out.print(weekend + " ");        //双休日:SATURDAY SUNDAY
20        }
21
22        //换行
23        System.out.println();
24
25        System.out.print("工做日:");
26        for (Weeks.WorkingDay workingDay : Weeks.WorkingDay.values()) {
27            System.out.print(workingDay + " ");     //工做日:MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY
28        }
29
30        //换行
31        System.out.println();
32
33        Weeks.WorkingDay friday = Weeks.WorkingDay.FRIDAY;
34        System.out.println("星期五:" + friday);      //星期五:FRIDAY
35    }
36}
image-20200608194649335
image-20200608194649335

八 枚举类集合

8.1 EnumSet集合

关于Set集合,咱们知道其集合中的元素是不重复的。其中的方法有如下几种:

返回值 方法 描述
static EnumSet<E> allOf(Class<E> elementType) 建立一个包含指定元素类型的全部元素的枚举 set。
EnumSet<E> clone() 返回一个set集合。
static EnumSet<E> complementOf(EnumSet<E> s) 建立一个其元素类型与指定枚举set相同的set集合(新集合中包含原集合所不包含的枚举成员)
static EnumSet<E> copyOf(EnumSet<E> s) 建立一个其元素类型与指定枚举 set 相同的枚举 set集合(新集合中包含与原集合相同的枚举成员)
static EnumSet<E> copyOf(Collection<E> s) 建立一个从指定 collection 初始化的枚举 set
static EnumSet<E> noneOf(Class<E> elementType) 建立一个具备指定元素类型的空枚举 set
static EnumSet<E> range(E from, E to) 建立一个最初包含由两个指定端点所定义范围内的全部元素的枚举 set。
static EnumSet<E> of 建立一个最初包含指定元素的枚举 set。注意:能够指定多个元素,因此在这里我没有列举参数
8.1.1 allOf

allOf方法须要咱们传入一个枚举的类对象,它会根据传入的枚举类对象生成一个具备该类对象枚举成员的Set集合。

1//建立一个包含Week全部枚举元素的Set集合
2EnumSet<Week> weeks = EnumSet.allOf(Week.class);
3System.out.println(weeks);              //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
4
5//打印Set集合中的元素
6for (Week week1 : weeks) {
7    System.out.print(week1 + " ");      //MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY
8}
8.1.2 clone

clone方法与直接打印枚举的Set集合结果相同!

1//返回一个Set集合
2System.out.println(weeks.clone());      //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
8.1.3 range

上面详细讲过枚举是有序数的,并且枚举类中的枚举成员是秉承着从左向右的顺序。因此咱们可使用range方法来建立指定枚举成员端点的Set集合,也就是说咱们须要传入枚举成员的起始与结束去建立一个该拥有该范围枚举成员的Set集合。以下:

1//建立一个最初包含由两个指定端点所定义范围内的全部元素的枚举 set。
2System.out.println(EnumSet.range(Week.MONDAY, Week.FRIDAY));        //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
8.1.4 complementOf

该方法有点特殊,它根据EnumSet去建立一个新Set集合。而新Set集合中枚举成员至关于旧Set集合中枚举成员的取反。

咱们用场景来模拟一下,当前Week枚举类中有星期一到星期日7个枚举成员。咱们使用range方法建立一个从星期一到星期五的Set集合(s1),随后我在将使用complementOf方法根据s1生成新的Set集合(s2),最后打印s2查看集合中的元素就只有星期六和星期日。

注意: 若是咱们的旧Set集合占据了枚举类中的全部枚举成员,在使用complementOf方法生成的新Set集合,新集合中的元素打印后为空Set,即[]

1//建立一个其元素类型与指定枚举set相同的set集合(新集合中包含原集合所不包含的枚举成员)
2EnumSet<Week> weeks1 = EnumSet.complementOf(weeks);
3System.out.println(weeks1);             //[]
4
5EnumSet<Week> range = EnumSet.range(Week.MONDAY, Week.FRIDAY);
6EnumSet<Week> weeks3 = EnumSet.complementOf(range);
7System.out.println(weeks3);                //[SATURDAY, SUNDAY]
8.1.5 copyOf

copyOf方法与complementOf相反,它建立一个新Set集合。而新Set集合中的枚举成员与旧Set集合中的枚举成员相同,这至关于就是Copy(复制功能)。若是你理解了complementOf方法,这个方法对你来讲也是没有挑战。如下我使用copyOf方法复制了一份weeks,其枚举成员一个很多。

注意: copyOf方法还有一个能够复制connection集合来建立Set集合,其connection集合中必须存储的是枚举成员。

1//建立一个其元素类型与指定枚举 set 相同的枚举 set集合(新集合中包含与原集合相同的枚举成员)
2EnumSet<Week> weeks2 = EnumSet.copyOf(weeks);
3System.out.println(weeks2);             //[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY]
1//复制存储枚举成员的HashSet集合
2Set set = new HashSet();
3set.add(Week.MONDAY);
4EnumSet set1 = EnumSet.copyOf(set);
5System.out.println(set1);        //[MONDAY]
8.1.6 of

of方法为咱们提供了选择性的便利,咱们能够挑选任意枚举成员成为Set集合的元素。

1//建立一个最初包含指定元素的枚举 set。
2System.out.println(EnumSet.of(Week.MONDAY,Week.FRIDAY));            //[MONDAY, FRIDAY]
8.1.7 noneOf

传入一个枚举的类对象去建立一个空Set集合

1EnumSet<Week> noneOf = EnumSet.noneOf(Week.class);
2System.out.println(noneOf);                     //[]

8.2 EnumMap集合

8.2.1 EnumMap集合的方法列表

关于Map集合,咱们知道它是由键和值组成。EnumMap集合与HashMap集合的效率比较来讲,EnumMap的效率高些。

关于EnumMap集合的使用与HashMap是一致的,没有什么特殊的。至于EnumMap集合的方法,我这里列举一下。

返回值 方法 描述
void clear() 移除全部映射关系。
EnumMap clone() 返回EnumMap集合。
boolean containsKey(Object key) 包含此键,则返回true
boolean containsValue(Object value) 包含一个或多个键映射到的该指定值,则返回true
Set > entrySet() 返回映射键值关系的Set集合
boolean equals(Object o) 比较对象与映射的相等关系
V get(Object key) 获取指定键映射的值,若是没有,返回null
Set<K> keySet() 返回全部键的Set集合
V put(K key, V value) 将指定键值存储在EnumMap集合中
void putAll(Map m) 将全部键值对存储在集合中
V remove(Object key) 若是存在映射关系,则移除该映射关系
int size() 返回存在映射关系的数量
Collection<V> values() 返回此映射中所包含值的 Collection集合
8.2.2 EnumMap集合的基本使用

因为EnumMap集合与HashMap集合基本类似,这里我就演示一下基本使用与HashMap不一样的地方。

EnumMap集合是咱们new出来的对象,建立出来的对象须要传入一个枚举的类对象,才返回一个Map集合。Map集合是键值对形式存储,因此咱们在写EnumMap集合的泛型时,根据需求来写,若是须要键是某枚举类型,咱们泛型就写它。若是有枚举类是值的要求,那就泛型中的值写枚举类。键值对都要求是枚举那也是OK的,咱们写泛型时都写需求的枚举类便可。除了建立对象和存储对象须要指定枚举类外,其余的与HashMap基本相同。

以下,我在建立EnumMap集合时执行的Week枚举类的类对象,泛型的键写的是Week枚举类,值写的Integer,这就意味着咱们在put(存储键值对)的时候,键须要存储Week枚举类中的枚举成员,值须要存储Integer数值。

1EnumMap<Week, Integer> map = new EnumMap<>(Week.class);
2map.put(Week.MONDAY, 1);
3map.put(Week.THURSDAY, 4);
4System.out.println(map);            //{MONDAY=1, THURSDAY=4}
相关文章
相关标签/搜索