¿Cómo inicializar directamente un HashMap (de forma literal)?

¿Existe alguna forma de inicializar un HashMap de Java 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 manera más corta/rápida de poner algunos valores "finales/estáticos" en un mapa que nunca cambian y se conocen de antemano al crear el Mapa.

Solución

Para Java versión 9 o superior:

Sí, esto es posible ahora. En Java 9 se han añadido un par de métodos de fábrica que simplifican la creación de mapas :

// this works for up to 10 elements:
Map test1 = Map.of(
    "a", "b",
    "c", "d"
);

// this works for any number of elements:
Map test2 = Map.ofEntries(
    entry("a", "b"),
    entry("c", "d")
);

En el ejemplo anterior tanto test como test2 serán lo mismo, sólo que con diferentes formas de expresar el Mapa. El método Map.of está definido para un máximo de diez elementos en el mapa, mientras que el método Map.ofEntries no tendrá ese límite.

Tenga en cuenta que en este caso el mapa resultante será un mapa inmutable. Si quieres que el mapa sea mutable, puedes copiarlo de nuevo, por ejemplo usando mutableMap = new HashMap(Map.of("a", "b"));.

(Ver también JEP 269 y el Javadoc)

Para hasta la versión 8 de Java:

No, tendrás que añadir todos los elementos manualmente. Puedes usar un inicializador en una subclase anónima para hacer la sintaxis un poco más corta:

Map myMap = new HashMap() {{
        put("a", "b");
        put("c", "d");
    }};

Sin embargo, la subclase anónima podría introducir un comportamiento no deseado en algunos casos. Esto incluye, por ejemplo:

  • Genera una clase adicional que aumenta el consumo de memoria, el consumo de espacio en disco y el tiempo de inicio
  • En el caso de un método no estático: Mantiene una referencia al objeto sobre el que se ha llamado al método de creación. Esto significa que el objeto de la clase externa no puede ser recogido de la basura mientras el objeto del mapa creado sigue siendo referenciado, bloqueando así la memoria adicional

El uso de una función para la inicialización también le permitirá generar un mapa en un inicializador, pero evita efectos secundarios desagradables:

Map myMap = createMap();

private static Map createMap() {
    Map myMap = new HashMap();
    myMap.put("a", "b");
    myMap.put("c", "d");
    return myMap;
}
Comentarios (13)

Esta es una forma.

HashMap h = new HashMap() {{
    put("a","b");
}};

Sin embargo, debes tener cuidado y asegurarte de que entiendes el código anterior (crea una nueva clase que hereda de HashMap). Por lo tanto, usted debe leer más aquí: http://www.c2.com/cgi/wiki?DoubleBraceInitialization o simplemente usar Guava:

Map left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Comentarios (13)
Map test = new HashMap()
{
    {
        put(key1, value1);
        put(key2, value2);
    }
};
Comentarios (8)