27. 不可变集合

本文介绍了Java中不可变集合的概念、特点,如不可变性、线程安全和性能优势。详细讲解了如何通过of()和copyOf()方法创建不可变集合,并提供了代码示例。强调了在多线程环境和性能优化中的应用。
摘要由CSDN通过智能技术生成

1. 概述

不可变集合是指一旦创建就不能被修改的集合对象。在不可变集合中,所有的操作都不会对原始集合对象进行更改,而是返回一个新的集合对象。

不可变集合的特点

  1. 不可变性:不可变集合对象的内容不能被修改。任何尝试修改集合的操作都会返回一个新的集合对象,原始集合对象保持不变。

  2. 线程安全:由于不可变集合无法被修改,因此可以在多线程环境中安全地共享。不需要额外的同步机制来保护集合的一致性。

  3. 可预测性:由于不可变集合是不可变的,因此其行为是可预测的。在不可变集合中,一旦创建了对象,它的值将永远不会改变,从而避免了潜在的副作用或不确定性。

需要注意的是,不可变集合并不适用于所有情况。如果需要频繁地进行集合修改操作,或者集合非常大,可能会对性能带来一些影响。在这种情况下,可以考虑使用可变集合并采取适当的同步措施。

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集合对象

细节

  1. 当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性
  2. 创建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. 注意事项

  1. 不可变集合是不可修改的

    一旦创建了不可变集合,就无法对其进行修改,包括添加、删除或修改元素。任何对不可变集合的修改操作都会导致UnsupportedOperationException异常。

  2. 不可变集合是线程安全的

    由于不可变集合是不可修改的,因此多个线程可以同时访问和使用不可变集合而无需进行同步。这使得不可变集合在多线程环境中更安全。

  3. 不可变集合不会保留对原始集合的引用

    创建不可变集合时,不会保留或引用原始集合的内部数据结构。这样可以确保不可变集合的完全独立性,从而避免了始料未及的副作用和不确定性。

  4. 不可变集合可以提高性能

    由于不可变集合的元素无法修改,因此可以进行一些优化,例如共享内部数据结构。这有助于提高性能,并减少内存开销。

  5. 不可变集合可以使用of()方法创建

    Java提供了of()方法,可以使用该方法直接创建指定元素的不可变集合。这种方式简单而方便,将元素作为参数传递给of()方法即可。

  6. 不可变集合可以通过拷贝现有集合来创建

    除了使用of()方法创建不可变集合外,还可以使用copyOf()方法通过拷贝现有集合来创建不可变集合。这种方式适用于需要将现有集合转换为不可变集合的情况。

  7. 不可变集合可以通过stream操作进行遍历和处理

    虽然不可变集合无法修改,但可以使用stream操作对集合进行遍历、过滤、映射等操作,以便处理集合中的元素并生成新的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷小洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值