2012-05-04 7 views
27

Estoy tratando de sopesar los pros y los contras de usar un EnumMap sobre un HashMap. Dado que, siempre buscaré utilizando un String, parece que un HashMap con una clave String sería la elección correcta. Sin embargo, un EnumMap parece mejor diseño porque transmite mi intención de restringir las claves a una enumeración específica. ¿Pensamientos?EnumMap o HashMap si la clave de búsqueda es una Cadena

Aquí está un ejemplo de fantasía, que muestra cómo me va a utilizar el 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; 
    } 
} 

asumir que la enumeración y AnimalType mapa sólo serán utilizados por el AnimalFactory para crear animales y en ninguna otra parte.

¿Cuál Map debo usar?

+0

@dogbane ¿algún progreso? – Javanator

Respuesta

12

Si se pueden enumerar todas las claves válidas, lo usaría ya que garantiza que siempre trabaje con un valor válido.

También puede evitar la confusión ya que String se puede utilizar para muchas cosas y es fácil convertir una cadena "Animal" en una cadena utilizada para otra cosa. Como los tipos enum no son intercambiables con otros tipos en general (a menos que use una interfaz común), hay menos posibilidades de error en la codificación.

+0

Dado que Animalum y el mapa SÓLO serán utilizados por AnimalFactory para crear animales y en ningún otro lado, ¿todavía crees que un EnumMap es mejor? ¿Qué piensa sobre el costo de convertir una cadena en una enumeración antes de la búsqueda cuando se utiliza un EnumMap? – dogbane

+1

Es casi lo mismo que el costo de buscar la Cadena en el Mapa en sí. No hay duplicación en EnumMap ya que es efectivamente un contenedor para una matriz. ;) –

0

La clave del mapa debe ser inmodificable y única, y esto se puede garantizar utilizando Enum.

También la administración sería más fácil y menos propensa a errores, en comparación a la administración de String.

So Go For EnumMap.

Además, como tenemos enumeraciones avanzadas, podemos adjuntar muchas otras informaciones y operaciones con las claves.

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

¿Cómo es "menos propenso a errores"? – dogbane

+0

no se incluirán las claves enumeradas en caso de enumeraciones y la gestión de las claves de las cadenas de constantes en algunas clases será un dolor de cabeza. Aunque menos palabras propensas a errores en mi comentario no fue el elemento centrado :) – Javanator

3

Si el conjunto de claves posibles es finito y conocido de antemano (como su ejemplo/pregunta sugerir), entonces la enumeración es una representación perfecta de esto. Como otros dijeron, el uso de una enumeración asegura que no se cometerán errores en el uso de la clave.

Por otra parte, esta implementación del mapa está muy optimizado, ya que el rango de las claves se conoce de antemano (en lo que a knwow, la EnumMap utiliza una matriz de longitud numberOfEnums internamente, indexada por el ordinal de la enumeración).

Así que también recomendaría EnumMap.

Dos (poco) cosas a tener en cuenta, sin embargo:

  • usted no será capaz de añadir casos especiales por herencia (no se puede extender una enumeración, así que no hay mapas de los animales con los mapas especializados de los mamíferos en el lado, por ejemplo)
  • al agregar un miembro a su enumeración, si lo agrega "en el medio" de los otros miembros, cambia los ordinales. Como esta información puede ser utilizada por el EnumMap, esto puede resultar problemático si vuelve a cargar un EnumMap construido a partir de la versión antigua de la enumeración (por ejemplo, usando serialización)
+0

como dices, un 'EnumMap 'es más rápido, pero existe el costo adicional de convertir la cadena de entrada en una enumeración antes de realizar la búsqueda. – dogbane

0

En primer lugar, todas las teclas que son finales inmutable. Definitivamente debe usar EnumMap.

Esto es como Hash en Ruby:

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

:font_size es el símbolo en Ruby, la contraparte estática final en Java.

Cuestiones relacionadas