簡體   English   中英

如果查找鍵是String,則為EnumMap或HashMap

[英]EnumMap or HashMap if lookup key is a String

我試圖權衡在HashMap上使用EnumMap優缺點。 因為,我將始終使用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

如果可以枚舉所有有效密鑰,我會使用它,因為它可以確保您始終使用有效值。

它還可以避免混淆,因為String可以用於很多事情,並且很容易將“Animal”字符串轉換為用於其他內容的字符串。 由於枚舉類型通常不能與其他類型互換(除非您使用通用接口),編碼錯誤的可能性較小。

如果可能鍵的集合是有限的並且事先已知(如您的示例/問題所示),那么枚舉就是對此的完美表示。 正如其他人所說,使用枚舉可確保在使用密鑰時不會出錯。

此外,Map的這種實現已經非常優化,因為密鑰的范圍是事先已知的(據我所知,EnumMap在內部使用長度為numberOfEnums的數組,由枚舉的序數索引)。

所以我也推薦EnumMap

但要注意兩件事(小事):

  • 你將無法通過繼承添加專門的案例(你不能擴展枚舉,所以沒有專門的MAMMALS地圖的ANIMALS地圖)
  • 將成員添加到枚舉時,如果將其添加到其他成員的“中間”,則更改序數。 由於這個信息可以被EnumMap使用,如果你重新加載從枚舉的舊版本構建的EnumMap(例如使用序列化),這可能會有問題。

Map的鍵應該是不可修改的和唯一的,這可以使用Enum保證。

與管理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;
  }

}

首先,所有密鑰都是最終不可變的。 你一定要使用EnumMap

這就像Ruby中的Hash:

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

:font_size是Ruby中的符號,是Java中的最終靜態對應物。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM