Immutable Map Implementations in Java – Java中不可变的地图实现

最后修改: 2018年 12月 5日

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

1. Overview

1.概述

It is sometimes preferable to disallow modifications to the java.util.Map such as sharing read-only data across threads. For this purpose, we can use either an Unmodifiable Map or an Immutable Map.

有时最好是不允许修改java.util.Map,比如跨线程共享只读数据。为此,我们可以使用Unmodifiable Map或Immutable Map。

In this quick tutorial, we’ll see what’s the difference between them. Then, we’ll present various ways in which we can create an Immutable Map.

在这个快速教程中,我们将看到它们之间有什么区别。然后,我们将介绍各种可以创建Immutable Map的方法。

2. Unmodifiable vs Immutable

2.不可改变与不可改变

An Unmodifiable Map is just a wrapper over a modifiable map and it doesn’t allow modifications to it directly:

不可修改的地图只是对可修改的地图的一个包装,它不允许直接对其进行修改:

Map<String, String> mutableMap = new HashMap<>();
mutableMap.put("USA", "North America");

Map<String, String> unmodifiableMap = Collections.unmodifiableMap(mutableMap);
assertThrows(UnsupportedOperationException.class,
  () -> unmodifiableMap.put("Canada", "North America"));

But the underlying mutable map can still be changed and the modifications are reflected in the Unmodifiable map as well:

但是,底层的可改变的地图仍然可以被改变,而且修改也会反映在不可改变的地图中。

mutableMap.remove("USA");
assertFalse(unmodifiableMap.containsKey("USA"));
		
mutableMap.put("Mexico", "North America");
assertTrue(unmodifiableMap.containsKey("Mexico"));

An Immutable Map, on the other hand, contains its own private data and doesn’t allow modifications to it. Therefore, the data cannot change in any way once an instance of the Immutable Map is created.

另一方面,Immutable Map包含它自己的私有数据,不允许对其进行修改。因此,一旦Immutable Map的实例被创建,数据就不能以任何方式改变。

3. Guava’s Immutable Map

3.瓜娃的不可变地图

Guava provides immutable versions of each java.util.Map using ImmutableMap. It throws an UnsupportedOperationException whenever we try to modify it.

Guava使用ImmutableMap为每个java.util.Map提供不可变的版本。每当我们试图修改它时,它就会抛出一个不支持操作的异常

Since it contains its own private data, this data won’t change when the original map is changed.

由于它包含自己的私有数据,当原始地图被改变时,这些数据不会改变。

We’ll now discuss various ways of creating instances of the ImmutableMap.

我们现在将讨论创建ImmutableMap.实例的各种方法。

3.1. Using copyOf() Method

3.1.使用copyOf()方法

First, let’s use the ImmutableMap.copyOf() method that returns a copy of all the entries as in the original map:

首先,让我们使用ImmutableMap.copyOf()方法,该方法返回一个与原始地图一样的所有条目的副本。

ImmutableMap<String, String> immutableMap = ImmutableMap.copyOf(mutableMap);
assertTrue(immutableMap.containsKey("USA"));

It cannot be modified directly or indirectly:

它不能被直接或间接修改。

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));
		
mutableMap.remove("USA");
assertTrue(immutableMap.containsKey("USA"));
		
mutableMap.put("Mexico", "North America");
assertFalse(immutableMap.containsKey("Mexico"));

3.2. Using builder() Method

3.2.使用builder()方法

We can also use ImmutableMap.builder() method to create a copy of all the entries as in the original map.

我们也可以使用ImmutableMap.builder()方法来创建一个与原始地图一样的所有条目的副本。

Moreover, we can use this method to add additional entries that are not present in the original map:

此外,我们可以用这种方法来增加原始地图中没有的额外条目。

ImmutableMap<String, String> immutableMap = ImmutableMap.<String, String>builder()
  .putAll(mutableMap)
  .put("Costa Rica", "North America")
  .build();
assertTrue(immutableMap.containsKey("USA"));
assertTrue(immutableMap.containsKey("Costa Rica"));

The same as in the previous example, we cannot modify it directly or indirectly:

与前面的例子一样,我们不能直接或间接地修改它。

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));
		
mutableMap.remove("USA");
assertTrue(immutableMap.containsKey("USA"));
		
mutableMap.put("Mexico", "North America");
assertFalse(immutableMap.containsKey("Mexico"));

3.3. Using of() Method

3.3.使用of()方法

Finally, we can use ImmutableMap.of() method to create an immutable map with a set of entries provided on the fly. It supports at most five key/value pairs:

最后,我们可以使用ImmutableMap.of()方法来创建一个具有一组即时提供的条目的不可变地图。它最多支持五个键/值对:

ImmutableMap<String, String> immutableMap
  = ImmutableMap.of("USA", "North America", "Costa Rica", "North America");
assertTrue(immutableMap.containsKey("USA"));
assertTrue(immutableMap.containsKey("Costa Rica"));

We cannot modify it as well:

我们也不能修改它。

assertThrows(UnsupportedOperationException.class,
  () -> immutableMap.put("Canada", "North America"));

4. Conclusion

4.总结

In this quick article, we discussed the differences between an Unmodifiable Map and Immutable Map.

在这篇快速文章中,我们讨论了不可修改的地图和不可改变的地图之间的区别。

We also had a look at different ways of creating Guava’s ImmutableMap.

我们也看了一下创建Guava的ImmutableMap的不同方法

And, as always, the complete code examples are available over on GitHub.

而且,像往常一样,完整的代码示例可在GitHub上获得