Java不可变地图的示例
在Java 9中,添加了新的静态工厂方法以在Java中创建不可变的Map。在本文中,我们将看到一个使用工厂方法创建不可变Map的示例,以及如何使它比以前使用Collections.unmodifiableMap()的选项更方便。
我们不能从不可变的Map中删除或者添加元素。调用Map上的任何mutator方法总是会引发UnsupportedOperationException。
在Java 9之前创建不可变或者不可修改的Map
在Java 9之前,Collections.unmodifiableMap()方法用于创建不可变的Map。使用此方法要注意的一件事是仍可以修改原始Map。
import java.util.Collections; import java.util.HashMap; import java.util.Map; public class ImmutMap { public static void main(String[] args) { Map<String, String> numMap = new HashMap<String, String>(); numMap.put("1", "One"); numMap.put("2", "Two"); numMap.put("3", "Three"); numMap.put("4", "Four"); Map<String, String> iMap = Collections.unmodifiableMap(numMap); // Original map can be changed numMap.put("5", "Five"); System.out.println("numMap" + numMap); //Throws exception as this Map is an unmodifiable view iMap.put("6", "Six"); } }
输出:
numMap{1=One, 2=Two, 3=Three, 4=Four, 5=Five} Exception in thread "main" java.lang.UnsupportedOperationException at java.base/java.util.Collections$UnmodifiableMap.put(Collections.java:1455) at com.theitroad.proj.Programs.ImmutMap.main(ImmutMap.java:19)
从输出numMap中可以看到,它是原始地图,仍可以修改(添加了一对新地图),但不可变地图无法修改。
向前创建不可变的地图Java 9
从Java 9开始,以下静态工厂方法提供了一种方便的方法来创建不可修改的映射。
- Map.of()(在Java 9中添加)
- Map.ofEntries()(在Java 9中添加)
- Map.copyOf()(在Java 10中添加)
这些方法创建的Map实例具有以下特征:
- 这些方法创建了不可修改的地图。键和值不能添加,删除或者更新。调用Map上的任何mutator方法总是会引发UnsupportedOperationException。但是,如果所包含的键或者值本身是可变的,则可能会导致Map行为不一致或者其内容似乎发生更改。
- 空键和值是不允许的。尝试使用空键或者空值创建它们会导致NullPointerException。
- 如果所有键和值都是可序列化的,则它们是可序列化的。
- 他们在创建时拒绝重复的密钥。传递给静态工厂方法的重复键会导致IllegalArgumentException。
- 映射的迭代顺序不确定,可能会发生变化。
Map.of()方法示例
此方法已重载,可以传递0到10个元素。
of()–返回包含零个映射的不可修改的映射。
of(K k1,V v1)–返回包含单个映射的不可修改的映射。
of(K k1,V v1,K k2,V v2)–返回包含两个映射的不可修改映射。
..
..
(K k1,V v1,K k2,V v2,K k3,V v3,K k4,V v4,K k5,V v5,K k6,V v6,K k7,V v7,K k8,V v8, K k9,V v9)–返回包含九个映射的不可修改的映射。
(K k1,V v1,K k2,V v2,K k3,V v3,K k4,V v4,K k5,V v5,K k6,V v6,K k7,V v7,K k8,V v8, K k9,V v9,K k10,V v10)–返回包含十个映射的不可修改的映射。
public class ImmutMap { public static void main(String[] args) { Map<String, String> numMap = Map.of("1", "One", "2", "Two", "3", "Three", "4", "Four"); System.out.println("numMap" + numMap); //Throws exception no change in Immutable Map numMap.put("5", "Five"); } }
输出:
numMap{3=Three, 4=Four, 1=One, 2=Two} Exception in thread "main" java.lang.UnsupportedOperationException at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72) at java.base/java.util.ImmutableCollections$AbstractImmutableMap.put(ImmutableCollections.java:731) at com.theitroad.proj.Programs.ImmutMap.main(ImmutMap.java:15)
Java Map.ofEntries()方法
如果我们有10个以上的键/值对,请使用Map.entry方法创建地图条目,然后将这些对象传递给Map.ofEntries方法。此方法返回一个不可修改的映射,其中包含从给定条目中提取的键和值。
public class ImmutMap { public static void main(String[] args) { Map<String, String> numMap = Map.ofEntries(entry("1", "One"), entry("2", "Two"), entry("3", "Three"), entry("4", "Four")); System.out.println("numMap" + numMap); } }
输出:
numMap{3=Three, 2=Two, 1=One, 4=Four}
Map.copyOf()方法示例
如果要从给定的Map创建一个不变的Map,则可以使用copyOf()方法。给定的Map不能为null,并且不得包含任何null键或者值。如果随后修改了给定的Map,则返回的Map将不会反映此类修改。
public class ImmutMap { public static void main(String[] args) { Map<String, String> numMap = new HashMap<String, String>(); numMap.put("1", "One"); numMap.put("2", "Two"); numMap.put("3", "Three"); numMap.put("4", "Four"); System.out.println("numMap- " + numMap); Map<String, String> iMap = Map.copyOf(numMap); System.out.println("iMap- " + iMap); numMap.put("5", "Five"); System.out.println("numMap after modification- " + numMap); System.out.println("iMap- " + iMap); } }
输出:
numMap- {1=One, 2=Two, 3=Three, 4=Four} iMap- {3=Three, 2=Two, 1=One, 4=Four} numMap after modification- {1=One, 2=Two, 3=Three, 4=Four, 5=Five} iMap- {3=Three, 2=Two, 1=One, 4=Four}
如我们所见,可以修改为创建不可变地图而复制的原始地图,但是该更改不会反映在不可变地图上。