1. Información general
En este tutorial, aprenderemos sobre varias formas de inicializar un HashMap en Java.
Usaremos Java 8 y Java 9.
2. El inicializador estático para un HashMap estático
Podemos inicializar un HashMap usando un bloque de código estático :
public static Map articleMapOne; static { articleMapOne = new HashMap(); articleMapOne.put("ar01", "Intro to Map"); articleMapOne.put("ar02", "Some article"); }
La ventaja de este tipo de inicialización es que el mapa es mutable, pero solo funcionará para estático. En consecuencia, las entradas se pueden agregar y eliminar cuando sea necesario.
Sigamos adelante y probémoslo:
@Test public void givenStaticMap_whenUpdated_thenCorrect() { MapInitializer.articleMapOne.put( "NewArticle1", "Convert array to List"); assertEquals( MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List"); }
También podemos inicializar el mapa usando la sintaxis de doble llave:
Map doubleBraceMap = new HashMap() {{ put("key1", "value1"); put("key2", "value2"); }};
Tenga en cuenta que debemos tratar de evitar esta técnica de inicialización porque crea una clase adicional anónima en cada uso, contiene referencias ocultas al objeto que lo encierra y puede causar problemas de pérdida de memoria.
3. Uso de colecciones de Java
Si necesitamos crear un mapa inmutable singleton con una sola entrada, Collections.singletonMap () se vuelve muy útil:
public static Map createSingletonMap() { return Collections.singletonMap("username1", "password1"); }
Tenga en cuenta que el mapa aquí es inmutable, y si intentamos agregar más entradas, arrojará java.lang.UnsupportedOperationException.
También podemos crear un mapa vacío inmutable usando Collections.emptyMap ():
Map emptyMap = Collections.emptyMap();
4. El modo Java 8
En esta sección, veamos las formas de inicializar un mapa usando Java 8 Stream API.
4.1. Usando Collectors.toMap ()
Usemos una secuencia de una matriz de cadenas bidimensional y recopilemos en un mapa:
Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }).collect(Collectors.toMap(data -> data[0], data -> data[1]));
Observe que aquí el tipo de datos de la clave y el valor del mapa es el mismo.
Para hacerlo más genérico, tomemos la matriz de Objetos y realicemos la misma operación:
Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
Como resultado, creamos un mapa de la clave como una Cadena y el valor como un Entero .
4.2. Uso de una secuencia de Map.Entry
Aquí usaremos las instancias de Map.Entry. Este es otro enfoque en el que tenemos diferentes tipos de claves y valores.
Primero, usemos la implementación SimpleEntry de la interfaz Entry :
Map map = Stream.of( new AbstractMap.SimpleEntry("idea", 1), new AbstractMap.SimpleEntry("mobile", 2)) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Ahora creemos el mapa usando la implementación SimpleImmutableEntry :
Map map = Stream.of( new AbstractMap.SimpleImmutableEntry("idea", 1), new AbstractMap.SimpleImmutableEntry("mobile", 2)) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
4.3. Inicializar un mapa inmutable
En ciertos casos de uso, necesitamos inicializar un mapa inmutable. Esto se puede hacer envolviendo Collectors.toMap () dentro de Collectors.collectingAndThen () :
Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }).collect(Collectors.collectingAndThen( Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap));
Tenga en cuenta que debemos evitar el uso de dicha inicialización mediante Streams, ya que podría causar una gran sobrecarga de rendimiento y se crean muchos objetos basura solo para inicializar el mapa.
5. El método Java 9
Java 9 viene con varios métodos de fábrica en la interfaz de mapas que simplifican la creación e inicialización de mapas inmutables.
Sigamos adelante y analicemos estos métodos de fábrica.
5.1. Mapa de()
This factory method takes no argument, a single argument, and variable arguments:
Map emptyMap = Map.of(); Map singletonMap = Map.of("key1", "value"); Map map = Map.of("key1","value1", "key2", "value2");
Note that this method supports only a maximum of 10 key-value pairs.
5.2. Map.ofEntries()
It's similar to the Map.of() but has no limitations on the number of key-value pairs:
Map map = Map.ofEntries( new AbstractMap.SimpleEntry("name", "John"), new AbstractMap.SimpleEntry("city", "budapest"), new AbstractMap.SimpleEntry("zip", "000000"), new AbstractMap.SimpleEntry("home", "1231231231") );
Note that the factory methods produce immutable maps, hence any mutation will result in a UnsupportedOperationException.
Also, they do not allow null keys or duplicate keys.
Now if we need a mutable or growing map after initialization, we can create any of the implementations of the Map interface and pass these immutable maps in the constructor:
Map map = new HashMap ( Map.of("key1","value1", "key2", "value2")); Map map2 = new HashMap ( Map.ofEntries( new AbstractMap.SimpleEntry("name", "John"), new AbstractMap.SimpleEntry("city", "budapest")));
6. Using Guava
As we've looked into the ways of using core Java, let's move ahead and initialize a map using the Guava library:
Map articles = ImmutableMap.of("Title", "My New Article", "Title2", "Second Article");
Esto crearía un mapa inmutable y crearía uno mutable:
Map articles = Maps.newHashMap(ImmutableMap.of("Title", "My New Article", "Title2", "Second Article"));
El método ImmutableMap.of () también tiene versiones sobrecargadas que pueden tomar hasta 5 pares de parámetros clave-valor. Así es como se vería un ejemplo con 2 pares de parámetros:
ImmutableMap.of("key1", "value1", "key2", "value2");
7. Conclusión
En este artículo exploramos las diversas formas de inicializar un mapa , particularmente para crear mapas vacíos, únicos, inmutables y mutables. Como podemos ver, hay una gran mejora en este campo desde Java 9.
Como siempre, el código fuente de muestra se encuentra en el proyecto Github. Los ejemplos de Java 9 se encuentran aquí y el ejemplo de Guava aquí.