Java不可变集合

不可变集合

定义:

​ 不可变集合,顾名思义,就是不可以被修改的集合。

​ 一旦该集合创建完毕,其长度和内容均不能改变(不能增、删、改元素),只能查找集合内的元素。

应用场景:

  1. 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中。
  2. 当集合对象被不可信的库调用的时候,不可变形式是安全的。

​ 简而言之:如果在创建集合的过程中不希望别人修改集合中的内容,那么就可以创建不可变集合,使得别人在使用此集合的时候只能进行查找操作(例如斗地主的牌的类型和数量,电脑启动时读取到的硬件型号等)。

创建不可变集合:

1、List和Set

​ JDK 8 通过Collections.unmodifiable集合类型() 方法将一个集合变为不可变集合,例如Collections.unmodifiableList()、Collections.unmodifiableSet()

​ JDK 9 可以通过对应集合的of()方法将一个集合变为不可变集合,例如List.of("张三", "李四");

of()方法是通过可变参数进行设置的:static List of(E… elements)

  // jdk8: 通过Collections.unmodifiab集合类型()方法将集合变为不可变
	List<Integer> list = new ArrayList<>();
  list.add(1);
  list.add(2);
  list.add(3);
  list = Collections.unmodifiableList(list);// 创建不可变List
	Set<String> set = new HashSet<>();
  set.add("a");
  set.add("b");
  set.add("c");
  set = Collections.unmodifiableSet(set);// 创建不可变Set
	// jdk9:通过对应集合的of()方法创建。
	List<String> list2 = List.of("张三", "李四", "王五", "赵六"); // 创建不可变List
	Set<String> set2 = Set.of("张三","李四","王五","赵六"); // 创建不可变Set

	// 可以进行正常的查询操作,但进行增删改操作将会报错
	set.remove("王五");
	set.add("aaa");
	// 上述两个方法将会报错:java.lang.UnsupportedOperationException
2、Map

​ JDK 8 依旧是使用Collections.unmodifiableMap()方法将一个集合变为不可变集合。

​ JDK 9可以使用Map.of()Map.ofEntries()但是有一些细节需要注意。

​ JDK 10可以使用Map.copyOf()来创建不可变集合。

	// jdk8:通过Collections.unmodifiableMap()方法将集合变为不可变
	Map<Integer,Integer> map = new HashMap<>();
  map.put(1,1);
  map.put(2,2);
  map = Collections.unmodifiableMap(map);
	// jdk9: 通过of()创建十个键值对以内的不可变Map,通过ofEntries()创建任意个数不可变Map。
	Map<String,String> map2 = Map.of("key1","value1","key2","value2");// 通过of()创建十个以内键值对的不可变集合。
	Map<String,String> map3 = Map.ofEntries(map.entrySet().toArray(new Map.Entry[0]));// 通过ofEntries()方法创建任意键值对的不可变集合。
	// jdk10:通过copyOf()方法创建
	Map<String,String> map4 = Map.copyOf(map);
	

of()方法介绍:

​ Map的of()方法通过重载,将2个参数(1个键值对)、4个参数(2个键值对)、… 、20个参数(10个键值对)的情况列举出来了,只支持最多是个键值对的创建。

​ 我们知道,一个方法的可变参数必须是方法的最后一个参数。

​ 而Map每个键值对是有两个参数,想要使用可变参数传递,如果将 key 和 value 分开传递,那么就需要传递两个可变参数:

public static<K,V> void of(K...keys,V...valuse){}

​ 很显然,这样写不可以,因为可变参数必须是方法的最后一个参数。

​ 因此需要将 Key 和 Value 看作一个整体 Entry,传递 Entry 类型的可变参数,这样就可以跟 List 和 Set一样了。这个方法名字就是:Map.ofEntries()

ofEntries()源码:

		@SafeVarargs
    @SuppressWarnings("varargs")
    static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
        if (entries.length == 0) { // implicit null check of entries array
            @SuppressWarnings("unchecked")
            var map = (Map<K,V>) ImmutableCollections.EMPTY_MAP;
            return map;
        } else if (entries.length == 1) {
            // implicit null check of the array slot
            return new ImmutableCollections.Map1<>(entries[0].getKey(),
                    entries[0].getValue());
        } else {
            Object[] kva = new Object[entries.length << 1];
            int a = 0;
            for (Entry<? extends K, ? extends V> entry : entries) {
                // implicit null checks of each array slot
                kva[a++] = entry.getKey();
                kva[a++] = entry.getValue();
            }
            return new ImmutableCollections.MapN<>(kva);
        }
    }

**ofEntries()**方法创建不可变集合详解:

	//由上述源码可知,ofEntries需要传入一个Entry类型的可变参数,所以需要先构造这个可变参数,也就是数组。
	// 1.拿到对应Map的Entry集合。
	Map<Integer,Integer> map = new HashMap<>();
  map.put(1,1);
  map.put(2,2);
	Set<Map.Entry<Integer,Integer>> entries = map.entrySet();
	// 2.创建Map.Entry类型的数组(当作泛型以及存储Entry转成数组后的变量)
	Map.Entry[] arr1 = new Map.Entry[0];
	// 3.通过toArray()方法将Set转化为数组:
	//  3.1 toArray()方法在底层会比较集合的长度(entries)和数组长度(arr1)的大小
	//   如果集合长度 > 数组长度:数据在数组中放不下,此时会根据集合中实际数据的个数重新创建数组。
	//   如果集合长度 <= 数组长度:数据在数组中放的下,此时不会创建新的数组,而是直接用传入的数组
	Map.Entry[] arr2 = entries.toArray(arr1); 
	// 4.将Entry数组转为不可变Map。
	Map map3 = Map.ofEntries(arr2); 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值