EnumMap 或 HashMap(如果查找键是字符串)

2022-09-01 13:25:46

我试图权衡使用一个.由于,我将永远使用a查找,似乎带有键的a将是正确的选择。但是,似乎更好的设计,因为它传达了我将键限制为特定枚举的意图。思潮?EnumMapHashMapStringHashMapStringEnumMap

这是一个虚构的例子,展示了我将如何使用: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;
    }
}

假设枚举和映射将仅由 用于创建动物,而不用于创建其他任何位置。AnimalTypeAnimalFactory

我应该使用哪个?Map


答案 1

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

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


答案 2

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

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

所以我也会推荐EnumMap

有两件(小)事情要记住:

  • 您将无法通过继承添加特殊情况(您无法扩展枚举,因此没有动物地图,例如侧面有专门的哺乳动物地图)
  • 将成员添加到枚举时,如果将其添加到其他成员的“中间”,则会更改序数。由于此信息可由 EnumMap 使用,因此,如果重新加载从旧版本的枚举构造的枚举(例如,使用序列化),这可能会带来问题。