web-dev-qa-db-fra.com

EnumMap ou Hashmap si la clé de recherche est une chaîne

J'essaie de peser les avantages et les inconvénients d'utiliser un EnumMap sur un HashMap. Depuis, je vais toujours chercher avec un String, il semble que un HashMap avec une clé String serait le bon choix. Cependant, un EnumMap semble être un meilleur design car il transmet mon intention de limiter les clés à une énumération spécifique. Les pensées?

Voici un exemple de croire, montrant comment je vais utiliser le 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;
    }
}

Supposons que le AnimalType Enum et la carte ne seront utilisés que par le AnimalFactory pour créer des animaux et nulle part ailleurs.

Quel Map devrais-je utiliser?

29
dogbane

Si l'ensemble des touches possibles est fini et connu à l'avance (comme votre exemple/question suggère), l'énum est une représentation parfaite de cela. Comme autre dit, l'utilisation d'un énumé garantit qu'aucune erreur ne sera faite dans l'utilisation de la clé.

En outre, cette mise en œuvre de la carte est assez optimisée, car la plage des touches est connue à l'avance (jusqu'à ce que je knwow, le sous -umma utilise une gamme de longueur NumberOfenumums Interne, indexé par l'ENUM ordinal).

Donc, je recommanderais également EnumMap.

Deux (petites) choses à garder à l'esprit cependant:

  • vous ne pourrez pas ajouter de cas spécialisés par héritage (vous ne pouvez pas étendre un énumé, donc aucune carte d'animaux avec des cartes spécialisées de mammifères sur le côté par exemple)
  • lorsque vous ajoutez un membre à votre énumé, si vous l'ajoutez "au milieu" des autres membres, vous modifiez les ordinaux. Comme cette information peut être utilisée par The EnumMap, cela peut s'avérer problématique si vous rechargez un EnumMap construit à partir de l'ancienne version de l'énumé (par exemple en utilisant la sérialisation)
3
Simon Baslé

La clé de la carte doit être non modifiable et unique et cela peut être gurante à l'aide de l'énum.

Gestion également qu'il serait plus facile et moins d'erreur sujette au comparateur de la gestion de la chaîne.

Alors allez pour Enumma.

De plus, comme nous avons avancé Enums, nous pouvons attacher de nombreuses autres informations et opérations avec les clés elles-mêmes.

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;
  }

}
0
Javanator

Tout d'abord, toutes vos clés sont définitives immuables. Vous devriez certainement utiliser EnumMap.

C'est comme Hash dans Ruby:

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

:font_size est le symbole de Ruby, la dernière homologue statique en Java.

0
Hao Deng