29

EnumMap我正在尝试权衡使用over a的利弊HashMap。因为,我将始终使用 a 进行查找String,似乎HashMap带有 aString键的 a 将是正确的选择。然而,一个EnumMap似乎更好的设计,因为它传达了我将键限制为特定枚举的意图。想法?

这是一个虚构的例子,展示了我将如何使用Map

enum AnimalType { CAT, DOG }
interface Animal {}
class Cat implements Animal {}
class Dog implements Animal {}

public class AnimalFactory {

    private static final Map<AnimalType, Animal> enumMap 
            = new EnumMap<AnimalType, Animal>(AnimalType.class);
    // versus
    private static final Map<String, Animal> stringMap 
            = new HashMap<String, Animal>();

    static {
        enumMap.put(AnimalType.CAT, new Cat());
        enumMap.put(AnimalType.DOG, new Dog());
        stringMap.put("CAT", new Cat());
        stringMap.put("DOG", new Dog());
    }
    public static Animal create(String type) {
        Animal result = enumMap.get(AnimalType.valueOf(type));
        Animal result2 = stringMap.get(type);
        return result;
    }
}

假设AnimalTypeenum 和 map 将仅被用于AnimalFactory创建动物而不是其他任何地方。

我应该使用哪个Map

4

4 回答 4

13

如果可以枚举所有有效键,我会使用它,因为它可以确保您始终使用有效值。

它还可以避免混淆,因为 String 可以用于很多事情,并且很容易将“Animal”字符串转换为用于其他用途的字符串。由于枚举类型通常不能与其他类型互换(除非您使用通用接口),因此编码出错的可能性较小。

于 2012-05-04T08:27:42.797 回答
3

如果一组可能的键是有限的并且事先已知(如您的示例/问题所建议的那样),那么枚举就是对此的完美表示。正如其他人所说,使用枚举确保在使用密钥时不会出错。

此外,这种 Map 的实现非常优化,因为键的范围是预先知道的(据我所知,EnumMap 在内部使用长度为numberOfEnums的数组,由枚举的序号索引)。

所以我也会推荐EnumMap

不过要记住两件(小)事情:

  • 您将无法通过继承添加特殊案例(例如,您不能扩展枚举,因此没有动物地图和专门的哺乳动物地图)
  • 将成员添加到枚举时,如果将其添加到其他成员的“中间”,则会更改序数。由于 EnumMap 可以使用此信息,因此如果您重新加载从旧版本枚举构造的 EnumMap(例如使用序列化),这可能会出现问题
于 2012-05-04T09:12:45.097 回答
0

首先,你所有的键都是最终不可变的。你绝对应该使用EnumMap.

这就像 Ruby 中的哈希:

options = { :font_size => 10, :font_family => "Arial" }

:font_size是 Ruby 中的符号,Java 中的最终静态对应物。

于 2013-07-02T13:16:30.037 回答
0

地图的键应该是不可修改和唯一的,这可以使用枚举来保证。

与管理 String 相比,管理它也会更容易,更不容易出错。

所以选择 EnumMap。

此外,由于我们有高级枚举,我们可以使用密钥本身附加许多其他信息和操作。

enum AnimalType {

  Dog("I am dog and I hate cats", true), 
  CAT("I am cat and I love to eat rats", true),
  RAT("I am a mouse and I love tearing human cloths apart", false) ;

  private final String description;
  private final boolean isHelpFullToHuman;

  private AnimalType(String description , boolean isHelpFullToHuman) {
     this.description = description;
     this.isHelpFullToHuman = isHelpFullToHuman;
  }

  public boolean isHelpFullToHuman() {
     return isHelpFullToHuman;
  }

  public String getDescription() {
     return description;
  }

}
于 2012-05-04T08:29:49.167 回答