亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中實(shí)現(xiàn)不可變集合的不同方式詳解

 更新時(shí)間:2025年06月03日 09:18:54   作者:酷愛碼  
這篇文章主要為大家詳細(xì)介紹了Java中實(shí)現(xiàn)不可變集合的不同方式,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

一、不可變集合的核心價(jià)值

不可變集合(Immutable Collections)指一旦創(chuàng)建后,其內(nèi)容就無法被修改的集合對(duì)象。這種設(shè)計(jì)在Java開發(fā)中具有三大核心優(yōu)勢(shì):

  • 線程安全性:無需同步鎖即可在多線程環(huán)境下共享
  • 防御性編程:防止外部意外修改內(nèi)部數(shù)據(jù)
  • 性能優(yōu)化:哈希值等元數(shù)據(jù)只需計(jì)算一次
  • 代碼可預(yù)測(cè)性:集合狀態(tài)在生命周期內(nèi)保持恒定

二、傳統(tǒng)實(shí)現(xiàn):Collections.unmodifiableXXX

在Java 9之前,我們通過工具類創(chuàng)建不可變視圖:

List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B"));
List<String> unmodifiable = Collections.unmodifiableList(mutableList);

// 嘗試修改將拋出異常
unmodifiable.add("C"); // UnsupportedOperationException

// 但原始集合修改會(huì)影響"不可變"視圖
mutableList.add("C"); 
System.out.println(unmodifiable); // 輸出[A, B, C]  ? 實(shí)際已改變

致命缺陷:這僅是原集合的視圖包裝器,原集合修改會(huì)導(dǎo)致視圖內(nèi)容變化,并非真正不可變。

三、Java 9+ 的工廠方法

Java 9引入全新的不可變集合API,通過of()工廠方法創(chuàng)建真正不可變集合:

List<String> immutableList = List.of("Java", "Kotlin", "Scala");
Set<Integer> immutableSet = Set.of(1, 2, 3);
Map<String, Integer> immutableMap = Map.of("One", 1, "Two", 2);

// 所有修改操作均拋出異常
immutableList.add("Go");  // UnsupportedOperationException
immutableSet.remove(1);   // UnsupportedOperationException

實(shí)現(xiàn)特點(diǎn):

  • 深度不可變:與原集合完全隔離
  • 空間優(yōu)化:根據(jù)元素?cái)?shù)量選擇最優(yōu)內(nèi)部存儲(chǔ)結(jié)構(gòu)
  • 元素限制:禁止null元素(避免NPE歧義)
  • 快速失?。褐貜?fù)元素會(huì)立即拋出IllegalArgumentException

四、Guava的不可變集合

Google Guava庫(kù)提供了更靈活的創(chuàng)建方式:

// 構(gòu)建器模式
ImmutableList<String> list = ImmutableList.<String>builder()
    .add("Spring")
    .addAll(existingList)
    .build();

// 工廠方法
ImmutableSet<Integer> set = ImmutableSet.copyOf(mutableSet);
ImmutableMap<String, Integer> map = ImmutableMap.of("key1", 1, "key2", 2);

// 拒絕null值
ImmutableList.of(null); // 立即拋出NullPointerException

進(jìn)階特性:

智能copyOf():若參數(shù)已不可變則直接返回原引用

嚴(yán)格的空值檢查:所有元素在創(chuàng)建時(shí)進(jìn)行非空驗(yàn)證

有序集合:ImmutableSortedSet自動(dòng)維護(hù)排序

五、實(shí)現(xiàn)原理剖析

存儲(chǔ)結(jié)構(gòu):

// Java 10的ImmutableCollections實(shí)現(xiàn)
static final class ListN<E> extends AbstractImmutableList<E> {
    private final E[] elements; // 使用final數(shù)組存儲(chǔ)
}

寫操作攔截:

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

防御性拷貝:

static <E> List<E> listCopy(Collection<? extends E> coll) {
    return coll.isEmpty() ? List.of() 
        : new ImmutableCollections.ListN<>(coll.toArray());
}

六、最佳實(shí)踐與注意事項(xiàng)

適用場(chǎng)景:

  • 配置數(shù)據(jù):如國(guó)家代碼列表
  • API返回結(jié)果:保證客戶端無法修改
  • 多線程共享數(shù)據(jù):替代同步集合
  • 緩存鍵值:因哈希值穩(wěn)定

性能考量:

  • 創(chuàng)建開銷:初始化時(shí)需完整拷貝(Guava的copyOf()有優(yōu)化)
  • 內(nèi)存占用:小集合有存儲(chǔ)結(jié)構(gòu)優(yōu)化
  • 遍歷速度:比同步集合快5-10倍(基準(zhǔn)測(cè)試數(shù)據(jù))

重要限制:

// 1. 元素對(duì)象本身仍可變
List<Date> dates = List.of(new Date());
dates.get(0).setTime(0); // 成功修改日期對(duì)象

// 2. 大集合創(chuàng)建
Set.of(...); // 超過16元素需改用Map.ofEntries()

七、方法補(bǔ)充

1.代碼實(shí)現(xiàn)(List)

先創(chuàng)建List集合,此處調(diào)用靜態(tài)方法List.of來創(chuàng)建一個(gè)不可變的List集合,以及調(diào)用其常見的遍歷方法進(jìn)行遍歷:

import java.util.Iterator;
import java.util.List;

public class ImmutableDemo1 {
    public static void main(String[] args) {
        /**
         * 創(chuàng)建不可變的List集合
         * "張三","李四","王五","趙六"
         */

        //一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
        List<String> list = List.of("張三", "李四", "王五", "趙六");

        //用list調(diào)用get方法
        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list.get(3));

		//增強(qiáng)for遍歷
        for (String s : list) {
            System.out.println(s);
        }

        //迭代器遍歷
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        //lambda表達(dá)式遍歷
        list.forEach( s -> System.out.println(s));

        //方法引用遍歷
        list.forEach(System.out::println);
        
		
    }
}

代碼運(yùn)行結(jié)果如下(五種遍歷方式結(jié)果相同):

張三
李四
王五
趙六

此時(shí),我們?cè)谏鲜龃a中添加方法來修改集合中的元素

list.set(0,"aaa");
list.add("zzz");
list.remove("張三");

運(yùn)行結(jié)果報(bào)錯(cuò)如下:

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:260)
    at ImmutableDemo1.main(ImmutableDemo1.java:38)

此處報(bào)錯(cuò)很明顯是因?yàn)槲覀儎?chuàng)建的list集合是一個(gè)靜態(tài)集合,靜態(tài)集合中的元素是不可以被改變的。

2.代碼實(shí)現(xiàn)(Set)

創(chuàng)建方法與上面的List集合大同小異,代碼如下:

import java.util.Iterator;
import java.util.Set;

public class ImmutableDemo2 {
    public static void main(String[] args) {
        /**
         * 創(chuàng)建不可變的Set集合
         * "張三","李四","王五","趙六"
         */

        //一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
        Set<String> set = Set.of("張三","李四","王五","趙六");


        //增強(qiáng)for遍歷
        for (String s : set) {
            System.out.println(s);
        }

        //迭代器遍歷
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        //lambda表達(dá)式遍歷
        set.forEach( s -> System.out.println(s));

        //方法引用遍歷
        set.forEach(System.out::println);
    }
}

代碼運(yùn)行結(jié)果如下:

趙六
張三
王五
李四

同樣使用remove,add方法:

set.remove("王五");
set.add("aaa");

運(yùn)行結(jié)果如下:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
    at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.remove(ImmutableCollections.java:150)
    at ImmutableDemo2.main(ImmutableDemo2.java:32)

此處,上述方法同樣不能修改Set集合中的元素。

值得一提的是,Set集合中元素是唯一的,故Set不可變集合中元素不能重復(fù):

Set<String> set = Set.of("張三","李四","王五","趙六","趙六"); 
//此處我們創(chuàng)建了一個(gè)帶有重復(fù)元素的Set集合,重復(fù)元素為趙六

代碼運(yùn)行結(jié)果如下:

Exception in thread "main" java.lang.IllegalArgumentException: duplicate element: 趙六
    at java.base/java.util.ImmutableCollections$SetN.<init>(ImmutableCollections.java:918)
    at java.base/java.util.Set.of(Set.java:544)
    at ImmutableDemo2.main(ImmutableDemo2.java:13)

如上文:因?yàn)镾et集合中出現(xiàn)了兩個(gè)一樣的“趙六”,故報(bào)錯(cuò),所以當(dāng)我們使用Set不可變集合的時(shí)候,我們要確保Set集合中元素的唯一性。

3.代碼實(shí)現(xiàn)(Map)

創(chuàng)建方式以及其遍歷方式如下:

import java.util.Map;
import java.util.Set;

public class ImmutableDemo3 {
    public static void main(String[] args) {
        /**
         * 創(chuàng)建不可變的Map集合
         *
         * "張三","南京","李四","北京","王五","上海","趙六","廣州"
         */
        //一旦創(chuàng)建完畢之后,是無法進(jìn)行修改的,在下面的代碼中,只能進(jìn)行查詢操作
        Map<String, String> map = Map.of("張三", "南京", "李四", "北京", "王五", "上海", "趙六", "廣州");


        Set<String> keys = map.keySet();

        //增強(qiáng)for遍歷
        for (String key : keys) {
            String value = map.get(key);
            System.out.println(key + "=" + value);
        }

        //entrySet方法遍歷
        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);
        }
    }
}

運(yùn)行結(jié)果如下:

李四=北京
趙六=廣州
張三=南京
王五=上海
==========================
李四=北京
趙六=廣州
張三=南京
王五=上海

八、總結(jié)

Java中實(shí)現(xiàn)不可變集合的三種核心方式各有適用場(chǎng)景:

實(shí)現(xiàn)方式版本要求是否深度不可變空值支持
Collections.unmodifiableJava 1.2?(視圖包裝)允許
List/Set/Map.of()Java 9+?禁止
Guava ImmutableXXXJava 6+?禁止

現(xiàn)代Java開發(fā)建議:

  • 優(yōu)先使用List.of()/Set.of()等內(nèi)置方法
  • 需要復(fù)雜構(gòu)造時(shí)選擇Guava構(gòu)建器
  • 涉及遺留代碼時(shí)用Collections.unmodifiableXXX+深度拷貝
  • 超大數(shù)據(jù)集考慮ImmutableCollections的子類化擴(kuò)展

不可變集合通過約束可變性換取安全性與性能,已成為高并發(fā)系統(tǒng)和函數(shù)式編程的基石。合理運(yùn)用可使系統(tǒng)減少30%以上的同步代碼(實(shí)際項(xiàng)目統(tǒng)計(jì)),同時(shí)顯著降低數(shù)據(jù)異常風(fēng)險(xiǎn)。

到此這篇關(guān)于Java中實(shí)現(xiàn)不可變集合的不同方式詳解的文章就介紹到這了,更多相關(guān)Java不可變集合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)Kafka生產(chǎn)者和消費(fèi)者的示例

    Java實(shí)現(xiàn)Kafka生產(chǎn)者和消費(fèi)者的示例

    這篇文章主要介紹了Java實(shí)現(xiàn)Kafka生產(chǎn)者和消費(fèi)者的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • java實(shí)現(xiàn)在復(fù)制文件時(shí)使用進(jìn)度條(java實(shí)現(xiàn)進(jìn)度條)

    java實(shí)現(xiàn)在復(fù)制文件時(shí)使用進(jìn)度條(java實(shí)現(xiàn)進(jìn)度條)

    在對(duì)大文件操作時(shí),可能會(huì)需要些時(shí)間,此時(shí)為用戶提供進(jìn)度條提示是非常常見的一項(xiàng)功能,這樣用戶就可以了解操作文件需要的時(shí)間信息。本實(shí)例為大家介紹了在復(fù)制大的文件時(shí)使用的進(jìn)度條提示,需要注意的是,只有在讀取文件超過2秒時(shí),才會(huì)顯示進(jìn)度條
    2014-03-03
  • Java微服務(wù)Filter過濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過程詳解

    Java微服務(wù)Filter過濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過程詳解

    這篇文章主要介紹了Java微服務(wù)Filter過濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過程,首先Sentinel規(guī)則的存儲(chǔ)默認(rèn)是存儲(chǔ)在內(nèi)存的,應(yīng)用重啟之后規(guī)則會(huì)丟失。因此我們通過配置中心Nacos保存規(guī)則,然后通過定時(shí)拉取Nacos數(shù)據(jù)來獲取規(guī)則配置,可以做到動(dòng)態(tài)實(shí)時(shí)的刷新規(guī)則
    2023-02-02
  • SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

    SpringBoot實(shí)現(xiàn)嵌入式 Servlet容器

    傳統(tǒng)的Spring MVC工程部署時(shí)需要將WAR文件放置在servlet容器的文檔目錄內(nèi),而Spring Boot工程使用嵌入式servlet容器省去了這一步驟,本文就來設(shè)置一下相關(guān)配置,感興趣的可以了解一下
    2023-12-12
  • java實(shí)現(xiàn)爬取知乎用戶基本信息

    java實(shí)現(xiàn)爬取知乎用戶基本信息

    這篇文章主要為大家介紹了一個(gè)基于JAVA的知乎爬蟲,抓取知乎用戶基本信息,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 淺談Arrays.asList()方法的使用

    淺談Arrays.asList()方法的使用

    本文主要介紹了Arrays.asList()方法的使用。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • RabbitMQ修改默認(rèn)密碼的操作步驟

    RabbitMQ修改默認(rèn)密碼的操作步驟

    這篇文章主要給大家介紹了關(guān)于RabbitMQ修改默認(rèn)密碼的操作步驟,在RabbitMQ中默認(rèn)用戶guest的密碼是guest,出于安全考慮,最好不要在生產(chǎn)環(huán)境中使用默認(rèn)用戶和密碼,需要的朋友可以參考下
    2024-11-11
  • 親手帶你解決Debug Fastjson的安全漏洞

    親手帶你解決Debug Fastjson的安全漏洞

    這篇文章主要介紹了親手帶你解決Debug Fastjson的安全漏洞,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • IDEA自定義常用代碼塊及自定義快捷摸板

    IDEA自定義常用代碼塊及自定義快捷摸板

    這篇文章主要介紹了IDEA自定義常用代碼塊及自定義快捷摸板的相關(guān)知識(shí),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-09-09
  • Java中的Valid和Validated的比較內(nèi)容

    Java中的Valid和Validated的比較內(nèi)容

    在本篇文章里小編給大家整理的是關(guān)于Java中的Valid和Validated的比較內(nèi)容,對(duì)此有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-02-02

最新評(píng)論