¿Hay alguna forma de inicializar un Java HashMap como este ?:
Map<String,String> test =
new HashMap<String, String>{"test":"test","test":"test"};
¿Cuál sería la sintaxis correcta? No he encontrado nada al respecto. es posible? Estoy buscando la forma más corta / más rápida de poner algunos valores "finales / estáticos" en un mapa que nunca cambian y que se conocen de antemano al crear el Mapa.
Respuestas:
Todas las versiones
En caso de que necesite una sola entrada: la hay
Collections.singletonMap("key", "value")
.Para Java Versión 9 o superior:
Sí, esto es posible ahora. En Java 9 se han agregado un par de métodos de fábrica que simplifican la creación de mapas:
En el ejemplo anterior, tanto
test
ytest2
será el mismo, sólo que con diferentes formas de expresar el Mapa. ElMap.of
método se define para hasta diez elementos en el mapa, mientras que elMap.ofEntries
método no tendrá dicho límite.Tenga en cuenta que en este caso el mapa resultante será un mapa inmutable. Si desea que el mapa sea mutable, puede copiarlo nuevamente, por ejemplo, usando
mutableMap = new HashMap<>(Map.of("a", "b"));
(Ver también JEP 269 y el Javadoc )
Para hasta Java Versión 8:
No, deberá agregar todos los elementos manualmente. Puede usar un inicializador en una subclase anónima para acortar un poco la sintaxis:
Sin embargo, la subclase anónima podría introducir comportamientos no deseados en algunos casos. Esto incluye, por ejemplo:
El uso de una función para la inicialización también le permitirá generar un mapa en un inicializador, pero evita los efectos secundarios desagradables:
fuente
Collections.singletonMap()
:)entry
documentado Java 9 ?Esta es una forma.
Sin embargo, debe tener cuidado y asegurarse de comprender el código anterior (crea una nueva clase que hereda de HashMap). Por lo tanto, debería leer más aquí: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , o simplemente usar Guava:
fuente
Si usted permite bibliotecas 3 ª parte, puede utilizar la guayaba 's ImmutableMap para lograr literal similar a la brevedad:
Esto funciona para hasta 5 pares clave / valor , de lo contrario puede usar su generador :
fuente
No hay una forma directa de hacer esto: Java no tiene literales de Map (todavía, creo que fueron propuestos para Java 8).
A algunas personas les gusta esto:
Esto crea una subclase anónima de HashMap, cuyo inicializador de instancia coloca estos valores. (Por cierto, un mapa no puede contener el doble del mismo valor, su segundo puesto sobrescribirá el primero. Usaré diferentes valores para los siguientes ejemplos).
La forma normal sería esta (para una variable local):
Si su
test
mapa es una variable de instancia, coloque la inicialización en un constructor o inicializador de instancia:Si su
test
mapa es una variable de clase, coloque la inicialización en un inicializador estático:Si desea que su mapa nunca cambie, debe después de la inicialización ajustar su mapa
Collections.unmodifiableMap(...)
. También puede hacer esto en un inicializador estático:(No estoy seguro de si ahora puede hacer la
test
final ... pruébelo e informe aquí).fuente
fuente
HashMap
esta subclase. Esto solo puede funcionar si realmente los proporciona. (Con un nuevo HashMap (vacío), los argumentos de tipo no son relevantes.)Una alternativa, usando clases y varargs simples de Java 7: cree una clase
HashMapBuilder
con este método:Use el método de esta manera:
fuente
tl; dr
Use
Map.of…
métodos en Java 9 y posteriores.Map.of
Java 9 agregó una serie de
Map.of
métodos estáticos para hacer exactamente lo que desea: crear una instancia de inmutableMap
usando sintaxis literal .El mapa (una colección de entradas) es inmutable, por lo que no puede agregar o quitar entradas después de crear instancias. Además, la clave y el valor de cada entrada son inmutables, no se pueden cambiar. Ver el Javadoc para ver otras reglas, como no se permiten NULL, no se permiten claves duplicadas y el orden de iteración de las asignaciones es arbitrario.
Veamos estos métodos, utilizando algunos datos de muestra para un mapa del día de la semana a una persona que esperamos que trabaje ese día.
Map.of()
Map.of
crea un vacioMap
. Inmodificable, por lo que no puede agregar entradas. Aquí hay un ejemplo de dicho mapa, vacío sin entradas.Map.of( … )
Map.of( k , v , k , v , …)
Hay varios métodos que toman de 1 a 10 pares clave-valor. Aquí hay un ejemplo de dos entradas.Map.ofEntries( … )
Map.ofEntries( Map.Entry , … )
toma cualquier número de objetos que implementan laMap.Entry
interfaz. Java agrupa dos clases que implementan esa interfaz, una mutable, la otra inmutable:AbstractMap.SimpleEntry
,AbstractMap.SimpleImmutableEntry
. Pero no necesitamos especificar una clase concreta. Simplemente necesitamos llamarMap.entry( k , v )
método, pasar nuestra clave y nuestro valor, y recuperamos un objeto de unaMap.Entry
interfaz de implementación de alguna clase .Map.copyOf
Java 10 agregó el método
Map.copyOf
. Pase un mapa existente, recupere una copia inmutable de ese mapa.Notas
Tenga en cuenta que el orden de los mapas iterador produce a través de
Map.of
son no garantizado. Las entradas tienen un orden arbitrario. No escriba código basado en el orden visto, ya que la documentación advierte que el pedido está sujeto a cambios.Tenga en cuenta que todos estos
Map.of…
métodos devuelven unMap
de una clase no especificada . La clase concreta subyacente puede incluso variar de una versión de Java a otra. Este anonimato permite a Java elegir entre varias implementaciones, lo que mejor se adapte a sus datos particulares. Por ejemplo, si sus claves provienen de una enumeración , Java podría usar unaEnumMap
debajo de las cubiertas.fuente
Posiblemente podría hacer su propio
Map.of
método (que solo está disponible en Java 9 y versiones posteriores) fácilmente de 2 maneras fácilesHazlo con una cantidad establecida de parámetros
Ejemplo
Hazlo usando una lista
También puede hacer esto usando una lista, en lugar de crear muchos métodos para un determinado conjunto de parámetros.
Ejemplo
Nota: No se recomienda usar esto para todo, ya que esto hace una clase anónima cada vez que usa esto.
fuente
JAVA 8
En java 8 simple también tienes la posibilidad de usar
Streams/Collectors
para hacer el trabajo.Esto tiene la ventaja de no crear una clase anónima.
Tenga en cuenta que las importaciones son:
Por supuesto, como se señaló en otras respuestas, en Java 9 en adelante tienes formas más simples de hacer lo mismo.
fuente
Desafortunadamente, usar varargs si el tipo de las claves y los valores no son los mismos no es muy razonable, ya que tendrías que usar
Object...
y perder completamente la seguridad del tipo. Si siempre desea crear, por ejemploMap<String, String>
, un , por supuesto, untoMap(String... args)
sería posible, pero no muy bonito, ya que sería fácil mezclar claves y valores, y un número impar de argumentos sería inválido.Puede crear una subclase de HashMap que tenga un método encadenable como
y úsalo como
new ChainableMap<String, Object>().set("a", 1).set("b", "foo")
Otro enfoque es usar el patrón de construcción común:
y úsalo como
new MapBuilder<String, Object>().put("a", 1).put("b", "foo").build();
Sin embargo, la solución que he usado de vez en cuando utiliza varargs y la
Pair
clase:Map<String, Object> map = Maps.of(Pair.create("a", 1), Pair.create("b", "foo");
La verbosidad de
Pair.create()
me molesta un poco, pero esto funciona bastante bien. Si no le importa las importaciones estáticas, por supuesto, podría crear un ayudante:Map<String, Object> map = Maps.of(p("a", 1), p("b", "foo");
(En lugar de lo que
Pair
uno podría imaginar usarMap.Entry
, pero como es una interfaz, requiere una clase de implementación y / o un método de fábrica auxiliar. Tampoco es inmutable y contiene otra lógica que no es útil para esta tarea).fuente
Puede usar Streams en Java 8 (esto es un ejemplo de Set):
Ref: https://www.baeldung.com/java-double-brace-initialization
fuente
Si necesita colocar solo un par clave-valor, puede usar Collections.singletonMap (clave, valor);
fuente