我试图权衡使用EnumMap
而不是HashMap
的利弊。因为,我将始终使用String
查找,似乎带有String
键的HashMap
是正确的选择。但是,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;
}
}
假设AnimalType
枚举和映射只会被AnimalFactory
用于创建动物,而不是其他地方。
我应该使用哪种Map
?
如果可以枚举所有有效键,我会使用它,因为它可以确保您始终使用有效值。
它还可以避免混淆,因为字符串可以用于很多事情,并且很容易将"动物"字符串转换为用于其他内容的字符串。由于枚举类型通常不能与其他类型的类型互换(除非您使用通用接口(,因此编码出错的可能性较小。
如果可能的键集是有限的并且事先知道(如您的示例/问题所建议的那样(,那么枚举就是对此的完美表示。正如其他人所说,使用枚举可确保在使用密钥时不会出错。
此外,Map 的这种实现是相当优化的,因为键的范围是事先知道的(据我所知,EnumMap 在内部使用一个长度 numberOfEnums 数组,由枚举的序数索引(。
所以我也会推荐EnumMap
.
不过要记住两件(小(事情:
- 您将无法通过继承添加特殊案例(您无法扩展枚举,因此例如,没有带有专门哺乳动物地图的动物地图(
- 将成员添加到枚举时,如果将其添加到其他成员的"中间",则会更改序号。由于此信息可以被 EnumMap 使用,因此如果您重新加载从旧版本的枚举构建的 EnumMap(例如使用序列化(,这可能会有问题
Map 的键应该是不可修改的和唯一的,这可以使用 Enum 来保证。
此外,与管理字符串相比,管理它会更容易且更不容易出错。
所以去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;
}
}
首先,所有密钥都是最终不可变的。 你绝对应该使用EnumMap
.
这就像 Ruby 中的 Hash:
options = { :font_size => 10, :font_family => "Arial" }
:font_size
是Ruby中的符号,Java中的最后一个静态对应物。