在Java中的不可变的Map实现

评论 0 浏览 0 2018-12-06

1.概述

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

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

2.不可更改与不可改变

不可修改的Map只是对可修改的Map的一个包装,它不允许直接修改。

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"));

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

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

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

3. Guava的不可变Map

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

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

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

3.1.使用copyOf()方法

首先,让我们使用ImmutableMap.copyOf()方法,该方法返回所有条目的副本,就像在原始Map中一样。

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

它不能被直接或间接地加以修改。

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.使用builder()方法

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

此外,我们还可以用这种方法来增加原始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"));

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

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.使用of()方法

最后,我们可以使用ImmutableMap.of()方法来创建一个不可变映射,其中包含一组动态提供的条目。它最多支持五个键/值对:

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

我们也不能修改它:

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

4.总结

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

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

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

最后更新2023-01-13
0 个评论
标签