java - enummap - enum map elixir
EnumMap o HashMap si la clave de búsqueda es una cadena (4)
En primer lugar, todas sus llaves son inmutables finales. Definitivamente deberías 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.
Estoy tratando de sopesar los pros y los contras de usar un EnumMap
sobre un HashMap
. Ya que siempre buscaré una String
, parece que un HashMap
con una tecla de String
sería la opción correcta. Sin embargo, un EnumMap
parece un mejor diseño porque transmite mi intención de restringir las claves a una enumeración específica. ¿Pensamientos?
Aquí hay un ejemplo ficticio, que muestra cómo usaré 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;
}
}
Supongamos que AnimalType
utilizará SOLAMENTE la enumeración y el mapa de AnimalFactory
para crear animales y en ningún otro lugar.
¿Qué Map
debo usar?
La clave del mapa debe ser inmodificable y única, y esto puede garantizarse mediante Enum.
También gestionarlo sería más fácil y menos propenso a errores en comparación con la gestión de String.
Así que vaya para EnumMap.
Además, como tenemos enumeraciones avanzadas, podemos adjuntar muchas otras informaciones y operaciones con las propias 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;
}
}
Si el conjunto de claves posibles es finito y conocido de antemano (como sugiere su ejemplo / pregunta), entonces la enumeración es una representación perfecta de esto. Como se dijo en otras palabras, el uso de una enumeración garantiza que no se cometan errores en el uso de la clave.
Además, esta implementación de Map está bastante optimizada, ya que el rango de las teclas se conoce de antemano (hasta donde sé, el EnumMap usa una serie de longitud numberOfEnums internamente, indexada por el ordinal del enum).
Así que también recomendaría EnumMap
.
Dos (pequeñas) cosas a tener en cuenta, sin embargo:
- no podrá agregar casos especializados por herencia (no puede extender una enumeración, por lo que no hay Mapas de ANIMALES con Mapas especializados de MAMÍFULOS 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 EnumMap, esto puede resultar problemático si vuelve a cargar un EnumMap construido a partir de la versión anterior de la enumeración (por ejemplo, mediante la serialización).
Si todas las claves válidas se pueden enumerar, lo utilizaría, ya que garantiza que siempre esté trabajando con un valor válido.
También puede evitar confusiones, ya que la cadena se puede usar para muchas cosas y es fácil convertir una cadena "Animal" en una cadena que se usa para otra cosa. Como los tipos de enumeración 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.