Wrong practice: Putting sets into an array indexed by the type's ordinal

/**

* Added demo for the "Use EnumMap instead of ordinal indexing".

*/

package com.effectivejava.EnumAnnotations;

/**

* @author Kaibo

*

*/

public class Herb {

public enum Type {

ANNUAL, PERENNIAL, BIENNIAL

}

private final String name;

public final Type type;

public 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 = ... ;

Set<Herb>[] herbsByType = // Indexed by Herb.Type.ordinal()

(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]);

}

Disadvantage of above case

  1. Arrays are not compatible with generics, so it requires an unchecked cast and will not compile cleanly.
  2. Array does not know what its index represents, it has to be labeled to the output manually.
  3. You have to be responsible to use the correct int value of an array; ints do not provide the type safety of enums.

Advantages of using EnumMap for multidimensional sets.

  1. Clarity
  2. Safety
  3. Ease of maintenance.

/**

* Added demo for the "Use EnumMap instead of ordinal indexing".

*/

package com.effectivejava.EnumAnnotations.unittest;

import java.util.EnumMap;

import java.util.HashSet;

import java.util.Map;

import java.util.Set;

import org.junit.Test;

import com.effectivejava.EnumAnnotations.Herb;

/**

* @author Kaibo

*

*/

public class HerbTest {

@Test

public void test() {

// Using ordinal() to index an array - DON'T DO THIS!

Herb[] garden = {new Herb("Flower1",Herb.Type.ANNUAL),

new Herb("Flower2",Herb.Type.BIENNIAL),

new Herb("Flower3",Herb.Type.BIENNIAL)} ;

// 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);

}

}

Summary

It is rarely appropriate to use ordinals to index arrays: use EnumMap instead. If the relationship that you are representing is multidimensional, use EnumMap<..., EnumMap<...>>.

/**

* Added multidimensional Enum types demo for the "Use EnumMap instead of ordinal indexing".

*/

package com.effectivejava.EnumAnnotations;

import java.util.EnumMap;

import java.util.Map;

/**

* @author Kaibo

*

*/

public enum Phase {

SOLID, LIQUID, GAS;

public enum Transition {

MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(

GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);

final Phase src;

final Phase dst;

Transition(Phase src, Phase dst) {

this.src = src;

this.dst = dst;

}

// Initialize the phase transition map

private static final Map<Phase, Map<Phase, Transition>> m = new EnumMap<Phase, Map<Phase, Transition>>(

Phase.class);

static {

for (Phase p : Phase.values())

m.put(p, new EnumMap<Phase, Transition>(Phase.class));

for (Transition trans : Transition.values())

m.get(trans.src).put(trans.dst, trans);

}

public static Transition from(Phase src, Phase dst) {

return m.get(src).get(dst);

}

}

}

Effective Java 33 Use EnumMap instead of ordinal indexing的更多相关文章

  1. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  2. 《Effective Java》读书笔记 - 6.枚举和注解

    Chapter 6 Enums and Annotations Item 30: Use enums instead of int constants Enum类型无非也是个普通的class,所以你可 ...

  3. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  4. Effective Java 第三版——37. 使用EnumMap替代序数索引

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Effective Java 第三版——33. 优先考虑类型安全的异构容器

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  7. 《Effective Java(中文第二版)》【PDF】下载

    <Effective Java(中文第二版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382186 Java(中文第二版)& ...

  8. Effective Java 第三版——35. 使用实例属性替代序数

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——38. 使用接口模拟可扩展的枚举

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. Android的Activity生命周期

    Android的Activity就相当于Windows Form中的Form,它的创建和销毁也是有一个生命周期的.主要经过这么7个阶段:   创建Activity:onCreate() 启动Activ ...

  2. [JS] JavaScript框架(1) jQuery

    jQuery使用户能更方便地处理HTML(标准通用标记语言下的一个应用).events.实现动画效果,并且方便地为网站提供AJAX交互.jQuery还有一个比较大的优势是,它的文档说明很全,而且各种应 ...

  3. jQuery的事件one

    如果你只想你设计的对象只能让用户执行一次的话,可以使用jQuery的事件one()来实现. 演示一个,创建视图, 看看效果:

  4. Matlab绘图(一二三维)

    Matlab绘图 强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数.此外,M ...

  5. Aspose.Word 操作word复杂表格 拆分单元格 复制行 插入行 文字颜色

    private void button3_Click(object sender, EventArgs e)         {             object savePathWord =&q ...

  6. [译]PrestaShop开发者指南 第一篇 基础

    # 第一篇 基础 PS(PrestaShop简称)一开始就设定了能够在它的基础上很简单的构建第三方模块的机制,让它成为一款具有极高定制性的电子商务软件. PS的可以在三个方面进行定制: * 主题 * ...

  7. Ubuntu14.04安装ROOT集群

    之前尝试在CentOS7上部署ROOT集群,却发现无论是源码包安装,还是官方提供的二进制包,都缺少了关键的xproofd可执行文件,导致PoD不能运行.没有办法,只能尝试在其他OS上部署,这里我选择了 ...

  8. 记录php日志

    1.记录PHP错误日志 display_errors与log_errors的区别 display_errors 错误回显,一般常用于开发模式,但是很多应用在正式环境中也忘记了关闭此选项.错误回显可以暴 ...

  9. redis3.0 集群实战3 - java编程实战

    本文主要描述使用jedis进行redis-cluster操作   jedis jedis是redis官方推荐使用的java redis客户端,github地址为,https://github.com/ ...

  10. webform(内置对象)

    一.内置对象 (一)Response - 响应请求对象1.定义:Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应.Response对象只提供了一个数据集合cookie ...