# 创建不可变集合
不可变集合就是一旦被创建后 长度不能修改 内容也不能修改的集合
# 不可变集合的应该场景
如果某个数据不能被修改,把它防御性的拷贝到不可变集合中是个很好的实践。
当集合对象被不可信的库调用时,不可变形式是安全的。
- 简单理解:不想让别人修改集合中的内容
# 创建不可变集合的书写格式
# 不可变集合分类
- List
- Set
- Map
在 List,Set,Map 接口中,都存在静态的 of 方法,可以获取一个不可变的集合。
方法名称 | 说明 |
---|---|
static <E> List<E> of(E...elements) | 创建一个具有指定元素的 List 集合对象 |
static <E> Set<E> of(E...elements) | 创建一个具有指定元素的 Set 集合对象 |
static <K,V> Map<K,V> of(E...elements) | 创建一个具有指定元素的 Map 集合对象 |
注意:这个集合不能添加,删除,修改。
# 演示 - List 不可变集合的创建和查询
public static void main(String[] args) { | |
// 创建不可变集合 内容为:"张三", "李四", "王五" | |
// 这个集合一旦创建后就不能添加,修改,删除了只能进行查询操作 | |
List<String> lists = List.of("张三", "李四", "王五"); | |
System.out.println("-------------get获取------------"); | |
System.out.println(lists.get(0)); | |
System.out.println(lists.get(1)); | |
System.out.println(lists.get(2)); | |
System.out.println("----------增强for----------"); | |
for (String list : lists) { | |
System.out.println(list); | |
} | |
System.out.println("----------iterator----------"); | |
Iterator<String> iterator = lists.iterator(); | |
while(iterator.hasNext()) { | |
System.out.println(iterator.next()); | |
} | |
} |
打印结果:
-------------get获取------------
张三
李四
王五
----------增强for----------
张三
李四
王五
----------iterator----------
张三
李四
王五
# 我们试下删除指定索引元素
public static void main(String[] args) { | |
// 创建不可变集合 内容为:"张三", "李四", "王五" | |
// 这个集合一旦创建后就不能添加,修改,删除了只能进行查询操作 | |
List<String> lists = List.of("张三", "李四", "王五"); | |
// 想要删除指定索引 1 的 不可变集合中的元素 | |
lists.remove(1); | |
} |
打印结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.remove(ImmutableCollections.java:260)
at jihe.Demo01.main(Demo01.java:11)
报错了。
# 我们试下添加元素
public static void main(String[] args) { | |
// 创建不可变集合 内容为:"张三", "李四", "王五" | |
// 这个集合一旦创建后就不能添加,修改,删除了只能进行查询操作 | |
List<String> lists = List.of("张三", "李四", "王五"); | |
// 想要向不可变集合中添加一个元素:"新成员" | |
lists.add("新成员"); | |
} |
打印结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
at jihe.Demo01.main(Demo01.java:11)
# 我们试下修改元素
public static void main(String[] args) { | |
// 创建不可变集合 内容为:"张三", "李四", "王五" | |
// 这个集合一旦创建后就不能添加,修改,删除了只能进行查询操作 | |
List<String> lists = List.of("张三", "李四", "王五"); | |
lists.set(1, "新成员"); | |
} |
打印结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.set(ImmutableCollections.java:262)
at jihe.Demo01.main(Demo01.java:11)
# 演示 - Set 不可变集合的创建
细节:创建时需要保证 of 中的元素唯一性不可重复否则报错。
public static void main(String[] args) { | |
Set<String> sets = Set.of("张三", "李四", "李四", "王五"); | |
} |
打印结果:
Exception in thread "main" java.lang.IllegalArgumentException: duplicate element: 李四
at java.base/java.util.ImmutableCollections$SetN.<init>(ImmutableCollections.java:925)
at java.base/java.util.Set.of(Set.java:524)
at jihe.Demo02.main(Demo02.java:7)
它说 "李四" 这个元素重复了
目前报错只能测试 添加,删除。不能测试修改因为 Set 集合不支持直接修改元素,而可以先删除旧元素在进行添加达到修改的目的
public static void main(String[] args) { | |
Set<String> sets = Set.of("张三", "李四", "王五"); | |
// 想要向不可变集合中添加一个元素 | |
sets.add("新成员"); | |
// sets.remove(1); | |
} |
打印结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
at jihe.Demo02.main(Demo02.java:9)
# 演示 - Map 不可变集合的创建
public static void main(String[] args) { | |
/** | |
* 细节 1:键不能重复 | |
* 细节 2:Map 里面的 of 方法,参数是有上限的,最多只能传递 20 个参数,10 个键值对 | |
* 细节 3:如果我们要传递多个键值对对象,数量大于 10 个,在 Map 接口中还有一个方法 | |
*/ | |
Map<String, String> maps = Map.of("o", "张三", "o1", "李四", "o2", "王五"); | |
System.out.println("-------------------"); | |
Set<String> sets = maps.keySet(); | |
for (String key : sets) { | |
System.out.println(key + " = " + maps.get(key)); | |
} | |
System.out.println("-------------------"); | |
Set<Map.Entry<String, String>> entrySet = maps.entrySet(); | |
for (Map.Entry<String, String> n : entrySet) { | |
String key = n.getKey(); | |
String value = n.getValue(); | |
System.out.println(key + " = " + value); | |
} | |
} |
打印结果:
-------------------
o1 = 李四
o = 张三
o2 = 王五
-------------------
o1 = 李四
o = 张三
o2 = 王五
同样不能进行添加和修改与删除否则报错
# Map 转键值对数组或不可变集合
public static void main(String[] args) { | |
/* | |
创建 Map 的不可变集合,键值对的数量超过 10 个 | |
*/ | |
//1. 创建一个普通的 Map 集合 | |
HashMap<String, String> hm = new HashMap<>(); | |
hm.put("张三", "南京"); | |
hm.put("李四", "北京"); | |
hm.put("王五", "上海"); | |
hm.put("赵六", "北京"); | |
hm.put("孙七", "深圳"); | |
hm.put("周八", "杭州"); | |
hm.put("吴九", "宁波"); | |
hm.put("郑十", "苏州"); | |
hm.put("刘一", "无锡"); | |
hm.put("陈二", "嘉兴"); | |
hm.put("aaa", "111"); | |
//2. 利用上面的数据来获取一个不可变的集合 | |
// 获取到所有的键值对对象(Entry 对象) | |
Set<Map.Entry<String, String>> entries = hm.entrySet(); | |
// 把 entries 变成一个数组 | |
// 创建一个空数组 | |
Map.Entry[] arr1 = new Map.Entry[0]; | |
//toArray:将 entries 中的键值对拷贝到 arr1 数组中 | |
//toArray 方法在底层会比较集合的长度跟数组的长度两者的大小 | |
// 如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组 | |
// 如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用 | |
Map.Entry[] arr2 = entries.toArray(arr1); | |
// 不可变的 map 集合 | |
Map map = Map.ofEntries(arr2); | |
// map.put("bbb","222"); | |
//Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0])); | |
// Map<String, String> map = Map.copyOf(hm); | |
// map.put("bbb", "222"); | |
} |