【从零开始学Java | 第三十篇】不可变集合

目录

前言

一、什么是不可变集合?

二、不可变集合使用方式

1.List不可变集合

2.Set不可变集合

3.Map不可变集合


前言

在日常的 Java 开发中,我们经常遇到这样的场景:你写了一个方法,返回一个包含了系统核心配置参数的普通的 ArrayList,其他调用者就可以随意地调用 .add().remove() 方法,悄悄篡改你的核心数据。**不可变集合(Immutable Collections)**就可以解决这个问题。

一、什么是不可变集合?

不可变集合就是一旦被创建,它的内容(元素数量、具体元素)就绝对不能再被修改的集合。 你不能向里面添加新元素,不能删除老元素,也不能替换现有的元素。

应用场景:

绝对的线程安全:因为数据不能被修改,所以多个线程同时读取它时,永远不需要加锁,没有任何并发冲突。

防御性编程:将不可变集合作为返回值传递给第三方模块,可以保证你的底层数据不会被恶意或无意地篡改。

更高的内存效率:不可变集合在底层不需要像 ArrayList 那样预留冗余空间来应对未来的扩容,它的内存占用更加紧凑。

二、不可变集合使用方式

方法名 说明
staitc <E> List<E> of(E...elements) 创建一个不可变List集合对象
staitc <E> Set<E> of(E...elements) 创建一个不可变Set集合对象
staitc <K, V> Map<K, V> of(E...elements) 创建一个不可变Map集合对象

1.List不可变集合

java 复制代码
public class Test {
    public static void main(String[] args) {
        List<String> l = List.of("张三", "李四", "王五");
        System.out.println(l);
        l.remove("张三");//报错:UnsupportedOperationException
    }
}

2.Set不可变集合

与List创建有异曲同工之妙。

java 复制代码
public class Test {
    public static void main(String[] args) {
        Set<String> l = Set.of("张三", "李四", "王五");
        System.out.println(l);
        l.remove("张三");//报错:UnsupportedOperationException
    }
}

细节:Set集合中不能有重复的元素

当我创建有重复元素的Set集合对象时:

java 复制代码
public class Test {
    public static void main(String[] args) {
        Set<String> s = Set.of("张三", "李四", "王五", "张三");
        System.out.println(s);
    }
}

3.Map不可变集合

细节1:Map和Set一样不能创建有重复元素的集合对象。

细节2:使用Map.of()创建Map集合对象时,最多存放10个键值对对象

正确使用方法①:

Map.ofEntries()

如何理解这段代码呢?

首先我们知道可变参数在底层其实就是数组,而Map.ofEntries()其中要传的参数是Entry类型

核心思想就是把Map类型的对象转换为Set再转换为Entry类型的数组。

java 复制代码
public class Test {
    public static void main(String[] args) {
        HashMap<String, String> hm = new HashMap<>();
        hm.put("001", "张三");
        hm.put("002", "李四");
        hm.put("003", "王五");

        Set<Map.Entry<String, String>> entries = hm.entrySet();

        Map.Entry[] array = entries.toArray(new Map.Entry[0]);
        Map<String, String> m = Map.ofEntries(array);
        
    }
}

正确使用方法②:

上面的太晦涩难懂了,因此在Java 10提出了copyOf()方法替代了上面的老旧方法。

java 复制代码
public class Test {
    public static void main(String[] args) {
        HashMap<String, String> hm = new HashMap<>();
        hm.put("001", "张三");
        hm.put("002", "李四");
        hm.put("003", "王五");

//        Set<Map.Entry<String, String>> entries = hm.entrySet();
//
//        Map.Entry[] array = entries.toArray(new Map.Entry[0]);
//        Map<String, String> m = Map.ofEntries(array);
//
        Map<String, String> m = Map.copyOf(hm);
    }
}
相关推荐
咩咩啃树皮5 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
灯澜忆梦6 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚6 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-6 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-6 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白7 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司8 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地9 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun3141599 小时前
TCP超时重传机制是为了解决什么问题?
java
段一凡-华北理工大学9 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化