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. 最近读cocoaui源代码有感

    上半年为了做一个ios的应用,引入了cocoaui库,主要是用来布局ios界面,发现简化了不少代码和工作量.因为在写第一个ios应用的时候,用的代码布局,在适配4s和6的机型时候,几乎被搞死,大量的约 ...

  2. JS数组追加数组采用push.apply的坑

    JS数组追加数组没有现成的函数,这么多年我已经习惯了a.push.apply(a, b);这种自以为很酷的,不需要写for循环的写法,一直也没遇到什么问题,直到今天我要append的b是个很大的数组时 ...

  3. IOS开发UI基础UIImagePickerController的属性

    UIImagePickerController 1.+(BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType ...

  4. Mysql大量插入随机数据方法--存储过程

    创建测试表: mysql)); 创建存储过程: mysql> delimiter // mysql> create procedure rand_data(in num int) -> ...

  5. JS 跨域问题常见的五种解决方式

    一.什么是跨域? 要理解跨域问题,就先理解好概念.跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来 ...

  6. 迭代接口的IEnumerator

    我们经常在工作中用到对List,Dictionary对象的Foreach遍历,取出每一项. 其实这个接口很简单,只有一个属性2个方法. [ComVisible(true), Guid("49 ...

  7. 回文串--- Girls' research

    HDU   3294 Problem Description One day, sailormoon girls are so delighted that they intend to resear ...

  8. Struts2执行过程解析

    说到Struts2执行过程就少不了一张图: 1 客户端初始化一个指向Servlet容器的请求: 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextClea ...

  9. Java编程思想读书笔记之内部类

    现在是够懒得了,放假的时候就想把这篇笔记写出来,一直拖到现在,最近在读<Java编程思想>,我想会做不止这一篇笔记,因为之前面试的时候总会问道一些内部类的问题,那这本书的笔记就从内部类开始 ...

  10. java微信开发(wechat4j)——得到微信请求参数

    微信平台会在请求的post数据中带有一些参数,例如用户的openid之类的信息,当你使用了wechat4j之后,得到这些信息是非常方便的. public class Lejian extends We ...