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. 【推荐】iOS带有加载网络图片进度的UIImageView

    UCZProgressView 是一个带有通用的圆形图片进度下载控件.动画效果不错 特性 Customizable indicator (line width, radius, and color) ...

  2. SQL查询作业执行情况

    查询作业的执行情况sql: SELECT [JobName] = JOB.name, [Step] = HIST.step_id, [StepName] = HIST.step_name, [Mess ...

  3. Asp.Net中动态页面转静态页面

    关于在Asp.Net中动态页面转静态页面的方法网上比较多.结合实际的需求,我在网上找了一些源代码,并作修改.现在把修改后的代码以及说明写一下. 一个是一个页面转换的类,该类通过静态函数Changfil ...

  4. 使scp不用输入密码

    使scp不用输入密码 有些时候,我们在复制/移动文件 到另一台机器时会用到scp,因为它比较安全.但如果每次都要输入密码,就比较烦了,尤其是在script里.不过,ssh有另一种用密钥对来验证的方式. ...

  5. mongodb学习5--mongo的type类型

    db.active.group({key:{id:1},cond:{cd:20160913,cid:"fgsdljsdv",aid:"54465"},reduc ...

  6. jdk1.8 ThreadPoolExecutor实现机制分析

    ThreadPoolExecutor几个重要的状态码字段 private static final int COUNT_BITS = Integer.SIZE - 3; private static ...

  7. Python可变参数

    #!/usr/bin/env python # -*- coding: utf-8 -*- import math def calc(*numbers): sum=0 for n in numbers ...

  8. mysql oom之后的page 447 log sequence number 292344272 is in the future

    mysql oom之后,重启时发生130517 16:00:10 InnoDB: Error: page 447 log sequence number 292344272InnoDB: is in ...

  9. Android详细的对话框AlertDialog.Builder使用方法

      我们在平时做开发的时候,免不了会用到各种各样的对话框,相信有过其他平台开发经验的朋友都会知道,大部分的平台都只提供了几个最简单的实现,如果我们想实现自己特定需求的对话框,大家可能首先会想到,通过继 ...

  10. 利用jQuery的淡入淡出实现轮播器

    基本原理:将所有图片绝对定位在同一位置,透明度设为0,然后通过jQuery的淡入淡出实现图片的切换效果: 但我在使用fadeIn淡入时却无效果,最后只能使用fadeTo实现,求大神指教 HTML: & ...