EnumMap:让Java Map更高效的技巧

科技   2024-11-06 11:31   山西  
今天咱们来聊一聊一个非常实用的Java技巧——EnumMap。这玩意儿是我在开发过程中偶然发现的,简直就像是Java中隐藏的一颗宝藏。
如果你经常用Map来做一些基于枚举类型的映射,估计这个工具会让你事半功倍,不信?那就往下看吧!
首先,简单介绍一下什么是EnumMap。很多时候,我们在写代码时会遇到这种需求:需要用Map来存储枚举值和对应的对象或数据。
正常来说,我们可能会用HashMap<EnumType, Object>来做这个映射。但是,这种方式在性能上并不总是最优,尤其是在枚举类型比较少的时候。
那么问题来了,Java到底有没有更高效的方式来处理这种映射呢?答案是有的!那就是EnumMap

# 什么是EnumMap?

EnumMap是Java Collections框架中的一个特例化的Map实现。顾名思义,它是专门用于枚举类型作为键的Map。它比HashMap在处理枚举键时要高效得多,原因是什么呢?我们可以通过下面的几个角度来理解:
  1. 内存优化EnumMap内部并不像HashMap那样使用哈希桶,它直接使用了枚举值的序号。这意味着在内存分配上,EnumMap会比HashMap更加高效,因为它不需要额外的空间来存储哈希码。
  2. 速度提升:由于它是根据枚举值的序号来存储数据,查找操作几乎是常数时间复杂度(O(1)),而不像HashMap那样需要计算哈希值,减少了性能开销。
  3. 类型安全EnumMap要求键必须是枚举类型,这就避免了错误地使用不合适的键类型,增强了类型安全。

# 如何使用EnumMap?

在使用EnumMap之前,首先你得了解一个条件:它只支持枚举类型的键。你不能在EnumMap中存储其他类型的对象,像String或者Integer这样的类型都不行。

基本的创建方式

创建EnumMap其实非常简单:
import java.util.EnumMap;

public class EnumMapExample {
    // 定义一个枚举类型
    enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }

    public static void main(String[] args) {
        // 创建一个EnumMap,键为Day枚举类型,值为String
        EnumMap<Day, String> enumMap = new EnumMap<>(Day.class);
        
        // 插入一些值
        enumMap.put(Day.MONDAY, "Start of the week");
        enumMap.put(Day.WEDNESDAY, "Midweek");
        enumMap.put(Day.FRIDAY, "Almost weekend");
        
        // 打印
        System.out.println(enumMap);
    }
}
运行上面的代码,你会看到如下输出:
{MONDAY=Start of the week, WEDNESDAY=Midweek, FRIDAY=Almost weekend}
看,这么简单就创建了一个基于枚举的Map,而且直接指定了枚举类型作为键。EnumMap的构造函数接受枚举类型的Class对象作为参数,所以它是类型安全的。

EnumMap的实现原理

EnumMap的实现非常有意思。它并不像HashMap那样通过链表和哈希桶来存储数据,而是使用了一个简单的数组来存储对应的值。为什么这么做呢?原因很简单——枚举值本身就是固定的,数量非常有限,因此EnumMap通过枚举的ordinal()方法(即枚举值的序号)来直接索引到一个数组的位置,进行存取操作。

内部存储

假设你定义了如下的枚举:
enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
EnumMap会创建一个数组,长度等于枚举值的个数(在这个例子中是7)。数组的每个索引位置会对应枚举中的每一个值。存取元素时,EnumMap只需要通过Day.MONDAY.ordinal()来快速定位到数组中的位置。这个方法返回的是MONDAY在枚举中的位置(0),这样就可以通过数组的索引直接存取数据了。

# EnumMap的例子

让我们看一个更复杂的例子,结合一些实际场景来理解EnumMap的应用。
假设你在开发一个简单的周日程管理系统,想要记录每一天的任务。这里,Day枚举类型就可以作为Map的键,而每天的任务作为值。
import java.util.EnumMap;

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

    public static void main(String[] args) {
        // 创建一个EnumMap,键为Day,值为String
        EnumMap<Day, String> taskMap = new EnumMap<>(Day.class);

        // 填充任务
        taskMap.put(Day.MONDAY, "Meeting with team");
        taskMap.put(Day.TUESDAY, "Code review");
        taskMap.put(Day.WEDNESDAY, "Research new tech");
        taskMap.put(Day.THURSDAY, "Write documentation");
        taskMap.put(Day.FRIDAY, "Deploy updates");
        taskMap.put(Day.SATURDAY, "Rest");
        taskMap.put(Day.SUNDAY, "Plan for next week");

        // 打印周日程
        taskMap.forEach((day, task) -> System.out.println(day + ": " + task));
    }
}
运行结果:
MONDAY: Meeting with team
TUESDAY: Code review
WEDNESDAY: Research new tech
THURSDAY: Write documentation
FRIDAY: Deploy updates
SATURDAY: Rest
SUNDAY: Plan for next week
从上面的例子可以看出,EnumMap不仅提供了非常高效的存取方式,而且在代码上也非常直观易懂。你只需知道一天的枚举类型,直接取出对应的任务就行了。

测试用例

既然说了这么多,怎么确保EnumMap真的是高效呢?我们来写个简单的性能对比测试,看看它和HashMap到底差距有多大。
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Map;

public class PerformanceTest {

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

    public static void main(String[] args) {
        // 创建HashMap和EnumMap
        Map<Day, String> hashMap = new HashMap<>();
        Map<Day, String> enumMap = new EnumMap<>(Day.class);

        // 插入1000000个数据进行对比
        long start = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashMap.put(Day.MONDAY, "Task " + i);
        }
        long end = System.nanoTime();
        System.out.println("HashMap插入耗时:" + (end - start) + "ns");

        start = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            enumMap.put(Day.MONDAY, "Task " + i);
        }
        end = System.nanoTime();
        System.out.println("EnumMap插入耗时:" + (end - start) + "ns");
    }
}
在大量数据插入的情况下,EnumMap的速度要比HashMap快得多。尤其在枚举类型的键值较少时,EnumMap的优势更加明显。

总结

好了,今天的内容到这里就差不多了。通过以上的介绍,你应该对EnumMap有了一个更深的了解。它不仅在性能上比HashMap更优,而且它的实现方式非常简单明了,适合用在需要频繁查找基于枚举类型映射的场景中。
兄弟们你们用上EnumMap了没?欢迎在评论区分享使用体验!
对编程、职场感兴趣的同学,可以链接我,微信:462135539 拉你进入“程序员交流群”。
🔥东哥私藏精品 热门推荐🔥

东哥作为一名超级老码农,整理了全网最全《Java高级架构师资料合集》
资料包含了《IDEA视频教程》《最全Java面试题库》、最全项目实战源码及视频》及《毕业设计系统源码》总量高达 650GB 。全部免费领取!全面满足各个阶段程序员的学习需求。

Java面试那些事儿
回复 java ,领取Java面试题。分享AI编程,Java教程,Java面试辅导,Java编程视频,Java下载,Java技术栈,AI工具,Java开源项目,Java简历模板,Java招聘,Java实战,Java面试经验,IDEA教程。
 最新文章