用好 Java 中的枚举,让你的工作效率飞起来!

本文详细介绍了 Java 中枚举类型 EnumSet 和 EnumMap 的使用,包括它们的特性、优势以及在实际场景中的应用。通过示例展示了如何使用 EnumSet 进行枚举常量的集合操作,以及如何利用 EnumMap 实现高效的数据映射。文章还提到了枚举在实现单例模式和策略模式中的作用,并探讨了 Java 8 中的 Stream API 如何简化 EnumSet 和 EnumMap 的操作。此外,还讨论了枚举在 JSON 表现形式和面试中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// Methods that set and get the status variable.

}

下面这段代码展示它是如何 work 的:

@Test

public void givenPizaOrder_whenReady_thenDeliverable() {

Pizza testPz = new Pizza();

testPz.setStatus(Pizza.PizzaStatus.READY);

assertTrue(testPz.isDeliverable());

}

6.EnumSet and EnumMap


6.1. EnumSet

EnumSet 是一种专门为枚举类型所设计的 Set 类型。

HashSet相比,由于使用了内部位向量表示,因此它是特定 Enum 常量集的非常有效且紧凑的表示形式。

它提供了类型安全的替代方法,以替代传统的基于int的“位标志”,使我们能够编写更易读和易于维护的简洁代码。

EnumSet 是抽象类,其有两个实现:RegularEnumSetJumboEnumSet,选择哪一个取决于实例化时枚举中常量的数量。

在很多场景中的枚举常量集合操作(如:取子集、增加、删除、containsAllremoveAll批操作)使用EnumSet非常合适;如果需要迭代所有可能的常量则使用Enum.values()

publicclass Pizza {

privatestatic EnumSet undeliveredPizzaStatuses =

EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY);

private PizzaStatus status;

publicenum PizzaStatus {

}

public boolean isDeliverable() {

returnthis.status.isReady();

}

public void printTimeToDeliver() {

System.out.println("Time to delivery is " +

this.getStatus().getTimeToDelivery() + " days");

}

public static List getAllUndeliveredPizzas(List input) {

return input.stream().filter(

(s) -> undeliveredPizzaStatuses.contains(s.getStatus()))

.collect(Collectors.toList());

}

public void deliver() {

if (isDeliverable()) {

PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy()

.deliver(this);

this.setStatus(PizzaStatus.DELIVERED);

}

}

// Methods that set and get the status variable.

}

下面的测试演示了展示了 EnumSet 在某些场景下的强大功能:

@Test

public void givenPizaOrders_whenRetrievingUnDeliveredPzs_thenCorrectlyRetrieved() {

List pzList = new ArrayList<>();

Pizza pz1 = new Pizza();

pz1.setStatus(Pizza.PizzaStatus.DELIVERED);

Pizza pz2 = new Pizza();

pz2.setStatus(Pizza.PizzaStatus.ORDERED);

Pizza pz3 = new Pizza();

pz3.setStatus(Pizza.PizzaStatus.ORDERED);

Pizza pz4 = new Pizza();

pz4.setStatus(Pizza.PizzaStatus.READY);

pzList.add(pz1);

pzList.add(pz2);

pzList.add(pz3);

pzList.add(pz4);

List undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList);

assertTrue(undeliveredPzs.size() == 3);

}

6.2. EnumMap

EnumMap是一个专门化的映射实现,用于将枚举常量用作键。与对应的 HashMap 相比,它是一个高效紧凑的实现,并且在内部表示为一个数组:

EnumMap<Pizza.PizzaStatus, Pizza> map;

让我们快速看一个真实的示例,该示例演示如何在实践中使用它:

publicstatic EnumMap<PizzaStatus, List>

groupPizzaByStatus(List pizzaList) {

EnumMap<PizzaStatus, List> pzByStatus =

new EnumMap<PizzaStatus, List>(PizzaStatus.class);

for (Pizza pz : pizzaList) {

PizzaStatus status = pz.getStatus();

if (pzByStatus.containsKey(status)) {

pzByStatus.get(status).add(pz);

} else {

List newPzList = new ArrayList();

newPzList.add(pz);

pzByStatus.put(status, newPzList);

}

}

return pzByStatus;

}

下面的测试演示了展示了 EnumMap 在某些场景下的强大功能:

@Test

public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() {

List pzList = new ArrayList<>();

Pizza pz1 = new Pizza();

pz1.setStatus(Pizza.PizzaStatus.DELIVERED);

Pizza pz2 = new Pizza();

pz2.setStatus(Pizza.PizzaStatus.ORDERED);

Pizza pz3 = new Pizza();

pz3.setStatus(Pizza.PizzaStatus.ORDERED);

Pizza pz4 = new Pizza();

pz4.setStatus(Pizza.PizzaStatus.READY);

pzList.add(pz1);

pzList.add(pz2);

pzList.add(pz3);

pzList.add(pz4);

EnumMap<Pizza.PizzaStatus,List> map = Pizza.groupPizzaByStatus(pzList);

assertTrue(map.get(Pizza.PizzaStatus.DELIVERED).size() == 1);

assertTrue(map.get(Pizza.PizzaStatus.ORDERED).size() == 2);

assertTrue(map.get(Pizza.PizzaStatus.READY).size() == 1);

}

7. 通过枚举实现一些设计模式


7.1 单例模式

通常,使用类实现 Singleton 模式并非易事,枚举提供了一种实现单例的简便方法。

《Effective Java 》和《Java与模式》都非常推荐这种方式,使用这种方式方式实现枚举可以有什么好处呢?

《Effective Java》

这种方法在功能上与公有域方法相近,但是它更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛采用,但是单元素的枚举类型已经成为实现 Singleton的最佳方法。—-《Effective Java 中文版 第二版》

《Java与模式》

《Java与模式》中,作者这样写道,使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。

下面的代码段显示了如何使用枚举实现单例模式:

publicenum PizzaDeliverySystemConfiguration {

INSTANCE;

PizzaDeliverySystemConfiguration() {

// Initialization configuration which involves

// overriding defaults like delivery strategy

}

private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL;

public static PizzaDeliverySystemConfiguration getInstance() {

return INSTANCE;

}

public PizzaDeliveryStrategy getDeliveryStrategy() {

return deliveryStrategy;

}

}

如何使用呢?请看下面的代码:

PizzaDeliveryStrategy deliveryStrategy = PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy();

通过 PizzaDeliverySystemConfiguration.getInstance() 获取的就是单例的 PizzaDeliverySystemConfiguration

7.2 策略模式

通常,策略模式由不同类实现同一个接口来实现的。

这也就意味着添加新策略意味着添加新的实现类。使用枚举,可以轻松完成此任务,添加新的实现意味着只定义具有某个实现的另一个实例。

下面的代码段显示了如何使用枚举实现策略模式:

publicenum PizzaDeliveryStrategy {

EXPRESS {

@Override

public void deliver(Pizza pz) {

System.out.println(“Pizza will be delivered in express mode”);

}

},

NORMAL {

@Override

public void deliver(Pizza pz) {

System.out.println(“Pizza will be delivered in normal mode”);

}

};

public abstract void deliver(Pizza pz);

}

Pizza增加下面的方法:

public void deliver() {

if (isDeliverable()) {

PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy()

.deliver(this);

this.setStatus(PizzaStatus.DELIVERED);

}

}

如何使用呢?请看下面的代码:

@Test

public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges() {

Pizza pz = new Pizza();

pz.setStatus(Pizza.PizzaStatus.READY);

pz.deliver();

assertTrue(pz.getStatus() == Pizza.PizzaStatus.DELIVERED);

}

8. Java 8 与枚举


Pizza 类可以用Java 8重写,您可以看到方法 lambda 和Stream API如何使 getAllUndeliveredPizzas()groupPizzaByStatus()方法变得如此简洁:

getAllUndeliveredPizzas():

public static List getAllUndeliveredPizzas(List input) {

return input.stream().filter(

(s) -> !deliveredPizzaStatuses.contains(s.getStatus()))

.collect(Collectors.toList());

}

groupPizzaByStatus() :

publicstatic EnumMap<PizzaStatus, List>

groupPizzaByStatus(List pzList) {

EnumMap<PizzaStatus, List> map = pzList.stream().collect(

Collectors.groupingBy(Pizza::getStatus,

() -> new EnumMap<>(PizzaStatus.class), Collectors.toList()));

return map;

}

9. Enum 类型的 JSON 表现形式


使用Jackson库,可以将枚举类型的JSON表示为POJO。下面的代码段显示了可以用于同一目的的Jackson批注:

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

码字不易,觉得有帮助的可以帮忙点个赞,让更多有需要的人看到

又是一年求职季,在这里,我为各位准备了一套Java程序员精选高频面试笔试真题,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考

以下是部分内容截图
架构面试专题及架构学习笔记导图.png

知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-oNpBJ9nV-1710428450877)]
[外链图片转存中…(img-QyllJkBH-1710428450878)]
[外链图片转存中…(img-kywpXPmq-1710428450878)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-dLKF4xoc-1710428450879)]

最后

码字不易,觉得有帮助的可以帮忙点个赞,让更多有需要的人看到

又是一年求职季,在这里,我为各位准备了一套Java程序员精选高频面试笔试真题,来帮助大家攻下BAT的offer,题目范围从初级的Java基础到高级的分布式架构等等一系列的面试题和答案,用于给大家作为参考

以下是部分内容截图
[外链图片转存中…(img-nKXjViZw-1710428450879)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值