Skip to main content
 首页 » 编程设计

Java 实现不可变Map

2022年07月19日128lvdongjie

Java 实现不可变Map

有时不希望修改java.util.Map,如线程间的共享数据。为此我们可以使用Unmodifiable Map 或 Immutable Map。本文讨论两者之间差异,然后给出不同方式创建不可变Map示例。

1. Unmodifiable vs Immutable

不可修改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")); 

我们希望不可变map包含它自己的私有数据,并且不允许对其进行修改。因此一旦创建了不可变map的实例,数据就不能以任何方式更改。

2. Guava’s Immutable Map

Guava提供不可修改map的实现ImmutableMap。如果尝试修改其数据会抛出UnsupportedOperationException 异常。因为其包括私有数据,当原始map被改变时该私有数据也不能被修改。下面讨论不同方式创建ImmutableMap:

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

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

2.3 使用of() 方法

最后我们使用ImmutableMap.of() 方法创建不可变map,创建时带一组元素,但最多不能超过5个键值对:

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

3. 总结

本文我们讨论了不能修改map和不能改变map之间差异。同时提供几种方式创建Guava’s ImmutableMap。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/109522289
阅读延展