Java 实现不可变Map

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值