Java中EnumMap代替序数索引代码详解

 更新时间:2018年02月01日 10:00:28   作者:司马懿字仲达  
这篇文章主要介绍了Java中EnumMap代替序数索引代码详解,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

本文研究的主要是Java中EnumMap代替序数索引的相关内容,具体介绍如下。

学习笔记《Effective Java 中文版 第2版》

经常会碰到使用Enum的ordinal方法来索引枚举类型。

public class Herb {
  public enum Type { ANNUAL, PERENNIAL, BIENNIAL };
  private final String name;
  private final Type type;

  Herb(String name, Type type) {
    this.name = name;
    this.type = type;
  }

  @Override public String toString() {
    return name;
  }
}

现在假设有一个香草的数组,表示一座花园中的植物,你想要按照类型(一年生、多年生或者两年生植物)进行组织之后再将这些植物列出来。如果要这么做的话,需要构建三个集合,每种类型一个,并且遍历整座花园,将每种香草放到相应的集合中。有些程序员会将这些集合放到一个按照类型的序数进行索引的数组来实现这一点。

//Using ordinal() to index an array - DON'T DO THIS
Herb[] garden = ... ;

//Indexed by Herb.Type.ordinal()
Set<Herb>[] herbsByType = (Set<Herb>[])new Set[Herb.Type.values().length]; 
for(int i=0; i<herbsByType.length; i++) {
  herbsByType[i] = new HashSet<Herb>();
}

for(Herb h : garden) {
  herbsByType[h.type.ordinal()].add(h);
}

//Print the results
for(int i=0; i<herbsByType.length; i++) {
  System.out.printf("%s: %s%n", Herb.Type.values()[i], herbsByType[i]);
}

这种方法的确可行,但是隐藏着许多问题。因为数组不能与泛型兼容。程序需要进行未受检的转换,并且不能正确无误地进行编译。因为数组不知道它的索引代表着什么,你必须手工标注这些索引的输出。但是这种方法最严重的问题在于,当你访问一个按照枚举的序数进行索引的数组时,使用正确的int值就是你的职责了;int不能提供枚举的类型安全。你如果使用了错误的值,程序就会悄然地完成错误的工作,或者幸运的话就会抛出ArrayIndexOutOfBoundException异常。

java.util.EnumMap是一种非常快速的Map实现专门用于枚举的键。

//Using an EnumMap to associate data with an enum
Map<Herb.Type, Set<Herb>> herbsByType = new EnumMap<Herb.Type, 
Set<Herb>>(Herb.Type.class);

for(Herb.Type t : Herb.Type.values)
  herbsByType.put(t, new HashSet<Herb>());

for(Herb h : garden)
  herbsByType.get(h.type).add(h);

System.out.println(herbsByType);

这段程序更简短,更清楚,也更安全,运行速度方面可以与使用序数的程序相媲美。它没有不安全的转换;不必手工标注出这些索引的输出,因为映射键知道如何将自身翻译成可打印的字符串的枚举;计算数组索引时也不可能出错。EnumMap在运行速度方面之所以能与通过序数索引的数组相媲美,是因为EnumMap在内部使用了这种数组。但是它对程序员隐藏了这种思想细节,集Map的丰富功能和类型安全与数组的快速于一身。注意EnumMap构造器采用键类型的Class对象:这是一个有限制的类型令牌(bounded type token),它提供了运行时的泛型信息。

总结

以上就是本文关于Java中EnumMap代替序数索引代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • 详解java动态代理模式

    详解java动态代理模式

    这篇文章主要为大家详细介绍了java动态代理模式,总结一下代理模式,以及jdk,cglib代理模式用法,来理解代理模式,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • SpringBoot中JPA更新时部分字段无效

    SpringBoot中JPA更新时部分字段无效

    本文主要介绍了SpringBoot中JPA更新时部分字段无效,在通过注解自动更新时,部分字段在调试时可以找到,却没有被自动更新到数据库中,下面就介绍一下解决方法
    2023-04-04
  • java使用链表实现约瑟夫环

    java使用链表实现约瑟夫环

    这篇文章主要为大家详细介绍了java使用链表实现约瑟夫环,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • bootstrap.yml如何读取nacos配置中心的配置文件

    bootstrap.yml如何读取nacos配置中心的配置文件

    这篇文章主要介绍了bootstrap.yml读取nacos配置中心的配置文件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 解读classpath读取resources目录下的文件

    解读classpath读取resources目录下的文件

    这篇文章主要介绍了解读classpath读取resources目录下的文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 解析Java异步之call future

    解析Java异步之call future

    当调用一个函数的时候,如果这个函数的执行过程是很耗时的,就必须要等待,但是有时候并不急着要这个函数返回的结果。因此,可以让被调者立即返回,让他在后台慢慢处理这个请求。对于调用者来说,可以先处理一些其他事情,在真正需要数据的时候再去尝试获得需要的数据
    2021-06-06
  • java实现短信通信的完整教程

    java实现短信通信的完整教程

    这篇文章主要为大家详细介绍了java实现短信通信的完整教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Java多线程案例之阻塞队列详解

    Java多线程案例之阻塞队列详解

    阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则.阻塞队列能是一种线程安全的数据结构。本文将通过一些示例为大家详细讲讲阻塞队列的原理与使用,感兴趣的小伙伴可以学习一下
    2022-10-10
  • Java 热更新 Groovy 实践及踩坑指南(推荐)

    Java 热更新 Groovy 实践及踩坑指南(推荐)

    Apache的Groovy是Java平台上设计的面向对象编程语言,这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用,这篇文章主要介绍了Java 热更新 Groovy 实践及踩坑指南,需要的朋友可以参考下
    2022-09-09
  • 基于maven中多个子模块的构建顺序

    基于maven中多个子模块的构建顺序

    这篇文章主要介绍了maven中多个子模块的构建顺序,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论