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。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用Collections.unmodifiableMap()方法创建不可map。这个方法将一个可map转换成一个不可map,该方法返回一个包装器对象,该对象实现Map接口,但不支持修改操作,任何修改操作都会抛出UnsupportedOperationException异常。 下面是一个示例代码: ```java import java.util.Collections; import java.util.HashMap; import java.util.Map; public class ImmutableMap { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("a", 1); map.put("b", 2); map.put("c", 3); Map<String, Integer> immutableMap = Collections.unmodifiableMap(map); System.out.println(immutableMap.get("a")); // Output: 1 System.out.println(immutableMap.size()); // Output: 3 immutableMap.put("d", 4); // Throws UnsupportedOperationException } } ``` 在这段示例代码中,我们首先创建了一个可map,然后使用Collections.unmodifiableMap()方法将其转换成了一个不可map。最后,我们分别使用get()和size()方法获取map中的元素和长度,并尝试进行修改操作,该操作会抛出UnsupportedOperationException异常。 需要注意的是,虽然不可map本身不能被修改,但是如果其包含的元素是可对象,那么这些可对象仍然可以被修改。因此,在使用不可map时需要注意其元素的可性。如果需要完全保证不可性,可以使用Java不可对象类,如Java 8中引入的Optional类、Java 9中引入的Immutable Collections等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值