1. 概述
不可变集合是指一旦创建就不能被修改的集合对象。在不可变集合中,所有的操作都不会对原始集合对象进行更改,而是返回一个新的集合对象。
不可变集合的特点:
-
不可变性:不可变集合对象的内容不能被修改。任何尝试修改集合的操作都会返回一个新的集合对象,原始集合对象保持不变。
-
线程安全:由于不可变集合无法被修改,因此可以在多线程环境中安全地共享。不需要额外的同步机制来保护集合的一致性。
-
可预测性:由于不可变集合是不可变的,因此其行为是可预测的。在不可变集合中,一旦创建了对象,它的值将永远不会改变,从而避免了潜在的副作用或不确定性。
需要注意的是,不可变集合并不适用于所有情况。如果需要频繁地进行集合修改操作,或者集合非常大,可能会对性能带来一些影响。在这种情况下,可以考虑使用可变集合并采取适当的同步措施。
2. 方法
方法声明 | 说明 |
---|---|
static List of(E…elements) | 创建一个具有指定元素的List集合对象 |
static Set of(E…elements) | 创建一个具有指定元素的Set集合对象 |
static <K,V> Map <K,V> of(E…elements) | 创建一个具有指定元素的Map集合对象 以表格的形式输出 |
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>… entries) | 创建一个具有指定键值对的不可变Map集合对象 |
static List copyOf(Collection<? extends E> coll) | 创建一个具有指定集合元素的不可变List集合对象 |
static Set copyOf(Collection<? extends E> coll) | 创建一个具有指定集合元素的不可变Set集合对象 |
static <K,V> Map<K,V> copyOf(Map<? extends K,? extends V> map) | 创建一个具有指定键值对的不可变Map集合对象 |
细节:
- 当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性
- 创建Map的不可变集合
-
细节1: 键是不能重复的
-
细节2:Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对
-
细节3:如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个
ofEntries()
方法和copyof()
方法copy()方法底层就是ofEntries方法,只不过java已经写好了的
Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));
-
3. 代码示例
-
不可变的list集合
public class ImmutableDemo1 { public static void main(String[] args) { /* 创建不可变的List集合 "张三", "李四", "王五", "赵六" */ //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作 List<String> list = List.of("张三", "李四", "王五", "赵六"); System.out.println(list.get(0)); System.out.println(list.get(1)); System.out.println(list.get(2)); System.out.println(list.get(3)); System.out.println("---------------------------"); for (String s : list) { System.out.println(s); } System.out.println("---------------------------"); Iterator<String> it = list.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } System.out.println("---------------------------"); for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } System.out.println("---------------------------"); //list.remove("李四"); //list.add("aaa"); list.set(0,"aaa"); } }
-
不可变的Set集合
public class ImmutableDemo2 { public static void main(String[] args) { /* 创建不可变的Set集合 "张三", "李四", "王五", "赵六" 细节: 当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性 */ //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作 Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六"); for (String s : set) { System.out.println(s); } System.out.println("-----------------------"); Iterator<String> it = set.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } System.out.println("-----------------------"); //set.remove("王五"); } }
-
不可变的Map集合
- 键值对个数小于等于10
public class ImmutableDemo3 { public static void main(String[] args) { /* 创建Map的不可变集合 细节1: 键是不能重复的 细节2: Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对 细节3: 如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个方法 */ //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作 Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海", "赵六", "广州", "孙七", "深圳", "周八", "杭州", "吴九", "宁波", "郑十", "苏州", "刘一", "无锡", "陈二", "嘉兴"); Set<String> keys = map.keySet(); for (String key : keys) { String value = map.get(key); System.out.println(key + "=" + value); } System.out.println("--------------------------"); Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry : entries) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "=" + value); } System.out.println("--------------------------"); } }
- 键值对个数大于10
public class ImmutableDemo4 { 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方法在底层会比较集合的长度跟数组的长度两者的大小 //如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组 //如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用 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"); } }
4. 注意事项
-
不可变集合是不可修改的
一旦创建了不可变集合,就无法对其进行修改,包括添加、删除或修改元素。任何对不可变集合的修改操作都会导致
UnsupportedOperationException
异常。 -
不可变集合是线程安全的
由于不可变集合是不可修改的,因此多个线程可以同时访问和使用不可变集合而无需进行同步。这使得不可变集合在多线程环境中更安全。
-
不可变集合不会保留对原始集合的引用
创建不可变集合时,不会保留或引用原始集合的内部数据结构。这样可以确保不可变集合的完全独立性,从而避免了始料未及的副作用和不确定性。
-
不可变集合可以提高性能
由于不可变集合的元素无法修改,因此可以进行一些优化,例如共享内部数据结构。这有助于提高性能,并减少内存开销。
-
不可变集合可以使用
of()
方法创建Java提供了
of()
方法,可以使用该方法直接创建指定元素的不可变集合。这种方式简单而方便,将元素作为参数传递给of()
方法即可。 -
不可变集合可以通过拷贝现有集合来创建
除了使用
of()
方法创建不可变集合外,还可以使用copyOf()
方法通过拷贝现有集合来创建不可变集合。这种方式适用于需要将现有集合转换为不可变集合的情况。 -
不可变集合可以通过stream操作进行遍历和处理
虽然不可变集合无法修改,但可以使用stream操作对集合进行遍历、过滤、映射等操作,以便处理集合中的元素并生成新的结果。