Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果查找键是字符串,则为EnumMap或HashMap_Java_Collections_Hashmap_Enum Map - Fatal编程技术网

Java 如果查找键是字符串,则为EnumMap或HashMap

Java 如果查找键是字符串,则为EnumMap或HashMap,java,collections,hashmap,enum-map,Java,Collections,Hashmap,Enum Map,我试图权衡使用EnumMap而不是HashMap的利弊。由于我总是使用字符串进行查找,因此使用字符串键的HashMap似乎是正确的选择。然而,EnumMap似乎是更好的设计,因为它传达了我将键限制到特定枚举的意图。想法 下面是一个虚构的示例,显示了我将如何使用地图: enum AnimalType { CAT, DOG } interface Animal {} class Cat implements Animal {} class Dog implements Animal {} publ

我试图权衡使用
EnumMap
而不是
HashMap
的利弊。由于我总是使用
字符串
进行查找,因此使用
字符串
键的
HashMap
似乎是正确的选择。然而,
EnumMap
似乎是更好的设计,因为它传达了我将键限制到特定枚举的意图。想法

下面是一个虚构的示例,显示了我将如何使用
地图

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;
    }
}
enum AnimalType{CAT,DOG}
界面动物{}
类Cat实现动物{}
类Dog实现动物{}
公营畜牧业{
私有静态最终映射枚举映射
=新枚举映射(AnimalType.class);
//对
私有静态最终映射stringMap
=新HashMap();
静止的{
enumMap.put(AnimalType.CAT,new CAT());
enumMap.put(AnimalType.DOG,newdog());
stringMap.put(“CAT”,new CAT());
stringMap.put(“DOG”,newdog());
}
公共静态动物创建(字符串类型){
动物结果=enumMap.get(AnimalType.valueOf(type));
动物结果2=stringMap.get(类型);
返回结果;
}
}
假设
AnimalType
enum和map仅由
AnimalFactory
用于创建动物,而不用于其他任何地方


我应该使用哪个
映射?

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


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

映射的键应该是不可修改且唯一的,并且可以使用枚举来保证这一点

与管理字符串相比,管理它更容易,也不容易出错

所以,选择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;
  }

}

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

此外,Map的这种实现是非常优化的,因为键的范围是预先知道的(据我所知,EnumMap在内部使用一个length numberofenum数组,由enum的序号索引)

因此,我还建议您使用EnumMap

但要记住两件事:

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

    • 首先,所有密钥都是最终不可变的。您肯定应该使用
      EnumMap

      这就像Ruby中的哈希:

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

      :font\u size
      是Ruby中的符号,是Java中最后一个静态对应项。

      鉴于AnimalFactory只会使用动物枚举和映射来创建动物,而不会在其他任何地方使用,您仍然认为枚举映射更好吗?使用EnumMap时,您认为在查找之前将字符串转换为enum的成本是多少?这与在映射本身中查找字符串的成本大致相同。EnumMap中没有加倍,因为它实际上是数组的包装器。;)正如您所说,
      EnumMap
      更快,但是,在执行查找之前将输入字符串转换为枚举会产生额外的成本。对于枚举,将不接受未列出的键,并且在某些类中管理字符串键常量将是一件令人头痛的事情。尽管我的注释中不太容易出错的单词不是重点元素:)