Initialize a HashMap in Java – 在Java中初始化一个HashMap

最后修改: 2018年 8月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll learn about various ways of initializing a HashMap in Java.

在本教程中,我们将学习在Java中初始化HashMap的各种方法。

We’ll use Java 8 as well as Java 9.

我们将使用Java 8以及Java 9。

2. The Static Initializer for a Static HashMap

2.静态HashMap的静态初始化器

We can initialize a HashMap using a static block of code:

我们可以使用一个静态代码块来初始化HashMap

public static Map<String, String> articleMapOne;
static {
    articleMapOne = new HashMap<>();
    articleMapOne.put("ar01", "Intro to Map");
    articleMapOne.put("ar02", "Some article");
}

The advantage of this kind of initialization is that the map is mutable, but it will only work for static. Consequently, entries can be added and removed as and when required.

这种初始化的好处是,地图是可变的,但它只对静态的东西有效。因此,条目可以在需要时被添加和删除。

Let’s go ahead and test it:

让我们继续测试一下吧。

@Test
public void givenStaticMap_whenUpdated_thenCorrect() {
    
    MapInitializer.articleMapOne.put(
      "NewArticle1", "Convert array to List");
    
    assertEquals(
      MapInitializer.articleMapOne.get("NewArticle1"), 
      "Convert array to List");  
}

We can also initialize the map using the double-brace syntax:

我们也可以用双括号的语法来初始化地图。

Map<String, String> doubleBraceMap  = new HashMap<String, String>() {{
    put("key1", "value1");
    put("key2", "value2");
}};

Note that we must try to avoid this initialization technique because it creates an anonymous extra class at every usage, holds hidden references to the enclosing object, and might cause memory leak issues.

请注意,我们必须尽量避免这种初始化技术,因为它在每次使用时都会创建一个匿名的额外类,持有对包围对象的隐藏引用,并可能导致内存泄漏问题。

3. Using Java Collections

3.使用Java集合

If we need to create a singleton immutable map with a single entry, Collections.singletonMap() becomes very useful:

如果我们需要创建一个只有一个条目的单子不可变地图,Collections.singletonMap() 就变得非常有用。

public static Map<String, String> createSingletonMap() {
    return Collections.singletonMap("username1", "password1");
}

Note that the map here is immutable, and if we try to add more entries, it’ll throw java.lang.UnsupportedOperationException.

请注意,这里的地图是不可变的,如果我们试图添加更多的条目,它会抛出java.lang.UnsupportedOperationException.

We can also create an immutable empty map by using Collections.emptyMap():

我们也可以通过使用Collections.emptyMap()创建一个不可变的空地图:

Map<String, String> emptyMap = Collections.emptyMap();

4. The Java 8 Way

4.Java 8的方式

In this section, let’s look into the ways to initialize a map using Java 8 Stream API.

在本节中,让我们来看看使用Java 8 Stream API初始化地图的方法。

4.1. Using Collectors.toMap()

4.1.使用Collectors.toMap()

Let’s use a Stream of a two-dimensional String array and collect them into a map:

让我们使用一个二维String数组的Stream,并将它们收集到一个地图中。

Map<String, String> map = Stream.of(new String[][] {
  { "Hello", "World" }, 
  { "John", "Doe" }, 
}).collect(Collectors.toMap(data -> data[0], data -> data[1]));

Notice here the data type of key and value of the Map is the same.

请注意,这里Map的key和value的数据类型是相同的。

In order to make it more generic, let’s take the array of Objects and perform the same operation:

为了让它更通用,让我们拿着Objects 的数组,执行同样的操作。

 Map<String, Integer> map = Stream.of(new Object[][] { 
     { "data1", 1 }, 
     { "data2", 2 }, 
 }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));

As a result, we create a map of the key as a String and value as an Integer.

因此,我们创建了一个键为String,值为Integer的映射。

4.2. Using a Stream of Map.Entry

4.2.使用Map.Entry的一个流

Here we’ll use the instances of Map.Entry. This is another approach where we have different key and value types.

这里我们将使用Map.Entry的实例。这是另一种方法,我们有不同的键和值类型。

First, let’s use SimpleEntry implementation of the Entry interface:

首先,让我们使用SimpleEntryEntry接口的实现。

Map<String, Integer> map = Stream.of(
  new AbstractMap.SimpleEntry<>("idea", 1), 
  new AbstractMap.SimpleEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Now let’s create the map using SimpleImmutableEntry implementation:

现在让我们使用SimpleImmutableEntry实现来创建地图。

Map<String, Integer> map = Stream.of(
  new AbstractMap.SimpleImmutableEntry<>("idea", 1),    
  new AbstractMap.SimpleImmutableEntry<>("mobile", 2))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

4.3. Initializing an Immutable Map

4.3.初始化一个不可变的地图

In certain use cases, we need to initialize an immutable map. This could be done by wrapping the Collectors.toMap() inside Collectors.collectingAndThen():

在某些用例中,我们需要初始化一个不可变的地图。这可以通过将Collectors.toMap()包裹在Collectors.collectionAndThen()中来完成。

Map<String, String> map = Stream.of(new String[][] { 
    { "Hello", "World" }, 
    { "John", "Doe" },
}).collect(Collectors.collectingAndThen(
    Collectors.toMap(data -> data[0], data -> data[1]), 
    Collections::<String, String> unmodifiableMap));

Note that we should avoid using such initialization using Streams, as it could cause a huge performance overhead and lots of garbage objects are created just to initialize the map.

注意,我们应该避免使用这样的初始化Streams,因为它可能会导致巨大的性能开销,并且仅仅为了初始化地图就会创建大量的垃圾对象。

5. The Java 9 Way

5.Java 9的方式

Java 9 comes with various factory methods in the Map interface that simplify the creation and initialization of immutable maps.

Java 9在Map接口中提供了各种工厂方法,以简化不可变的地图的创建和初始化。

Let’s go ahead and look into these factory methods.

让我们继续研究这些工厂方法。

5.1. Map.of()

5.1.Map.of()

This factory method takes no argument, a single argument, and variable arguments:

这个工厂方法不接受任何参数,只接受一个参数,以及可变参数。

Map<String, String> emptyMap = Map.of();
Map<String, String> singletonMap = Map.of("key1", "value");
Map<String, String> map = Map.of("key1","value1", "key2", "value2");

Note that this method supports only a maximum of 10 key-value pairs.

注意,这个方法最多只能支持10个键值对。

5.2. Map.ofEntries()

5.2.Map.ofEntries()

It’s similar to the Map.of() but has no limitations on the number of key-value pairs:

它类似于Map.of() ,但对键值对的数量没有限制。

Map<String, String> map = Map.ofEntries(
  new AbstractMap.SimpleEntry<String, String>("name", "John"),
  new AbstractMap.SimpleEntry<String, String>("city", "budapest"),
  new AbstractMap.SimpleEntry<String, String>("zip", "000000"),
  new AbstractMap.SimpleEntry<String, String>("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<String, String> map = new HashMap<String, String> (
  Map.of("key1","value1", "key2", "value2"));
Map<String, String> map2 = new HashMap<String, String> (
  Map.ofEntries(
    new AbstractMap.SimpleEntry<String, String>("name", "John"),    
    new AbstractMap.SimpleEntry<String, String>("city", "budapest")));

6. Using Guava

6.使用番石榴

As we’ve looked into the ways of using core Java, let’s move ahead and initialize a map using the Guava library:

我们已经了解了使用核心Java的方法,让我们继续前进,使用Guava库初始化一个地图。

Map<String, String> articles 
  = ImmutableMap.of("Title", "My New Article", "Title2", "Second Article");

This would create an immutable map, and to create a mutable one:

这将创建一个不可变的地图,并创建一个可变的地图。

Map<String, String> articles 
  = Maps.newHashMap(ImmutableMap.of("Title", "My New Article", "Title2", "Second Article"));

The method ImmutableMap.of() also has overloaded versions that can take up to 5 pairs of key-value parameters. Here’s what an example with 2 pairs of parameters would look like:

该方法ImmutableMap.of()也有重载版本,可以接受多达5对键值参数。下面是一个有2对参数的例子,看起来是这样的。

ImmutableMap.of("key1", "value1", "key2", "value2");

7. Conclusion

7.结语

In this article we explored the various ways of initializing a Map, particularly to create empty, singleton, immutable and mutable maps. As we can see, there’s a huge improvement in this field since Java 9. 

在这篇文章中,我们探讨了初始化Map的各种方法,尤其是创建空、单子、不可变和可变的地图。正如我们所见,自Java 9以来,这一领域有了巨大的改进。

As always, the sample source code is located in the Github project. The Java 9 examples are located here, and the Guava sample here.

一如既往,示例源代码位于Github项目中。Java 9的示例位于这里,而Guava的示例这里