zoukankan      html  css  js  c++  java
  • Effective Java 33 Use EnumMap instead of ordinal indexing

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

    }

    }

    }

  • 相关阅读:
    struct 结构体解析(原)
    C++标准编程:虚函数与内联
    基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现
    直接用编译器按ctrl+F5运行和双击运行结果不一样
    驱动编译的时候注意编译工程选项
    驱动编译的时候注意编译工程选项
    'ddkbuild.cmd' 不是内部或外部命令,也不是可运行的程序
    'ddkbuild.cmd' 不是内部或外部命令,也不是可运行的程序
    NtOpenProcess被HOOK,跳回原函数地址后仍然无法看到进程
    NtOpenProcess被HOOK,跳回原函数地址后仍然无法看到进程
  • 原文地址:https://www.cnblogs.com/haokaibo/p/use-EnumMap-instead-of-ordinal-indexing.html
Copyright © 2011-2022 走看看