Java中不可變集合的實(shí)現(xiàn)方式
前言
在 Java 編程中,不可變集合(Immutable Collection) 是指其內(nèi)容在創(chuàng)建后不能被修改的集合。不可變集合在多線程編程中具有重要作用,因?yàn)樗梢源_保數(shù)據(jù)的一致性和安全性,避免了多線程訪問(wèn)時(shí)的競(jìng)爭(zhēng)條件和同步問(wèn)題。此外,不可變集合通常也具有性能優(yōu)勢(shì),因?yàn)樗鼈儾恍枰M(jìn)行同步操作,且能夠減少內(nèi)存復(fù)制。
在本文中,我們將深入探討 Java 中如何實(shí)現(xiàn)不可變集合,具體的實(shí)現(xiàn)方式,以及它們?cè)诓煌瑘?chǎng)景下的應(yīng)用。
1. 不可變集合的特性
不可變集合的主要特性包括:
- 不可修改性:一旦創(chuàng)建,就不能對(duì)集合中的元素進(jìn)行添加、刪除、修改等操作。
- 線程安全:由于集合的內(nèi)容不可變,因此天然是線程安全的,不需要額外的同步機(jī)制。
- 提高性能:不可變對(duì)象通??梢怨蚕砗途彺?,避免了不必要的副本,提升了內(nèi)存效率。
2. Java 中不可變集合的實(shí)現(xiàn)方式
Java 中實(shí)現(xiàn)不可變集合的方式有多種,下面我們將討論幾種常見(jiàn)的方法。
2.1. 使用 Collections.unmodifiableXXX() 方法
Java 提供了 Collections
類(lèi)中的一系列靜態(tài)方法,可以將現(xiàn)有的集合包裝成不可變的集合。常見(jiàn)的方法有:
unmodifiableList()
:將List
轉(zhuǎn)換為不可修改的列表。unmodifiableSet()
:將Set
轉(zhuǎn)換為不可修改的集合。unmodifiableMap()
:將Map
轉(zhuǎn)換為不可修改的映射。
import java.util.*; public class ImmutableExample { public static void main(String[] args) { // 創(chuàng)建一個(gè)普通的集合 List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); // 將集合轉(zhuǎn)換為不可修改的集合 List<String> immutableList = Collections.unmodifiableList(list); // 嘗試修改不可變集合會(huì)拋出異常 // immutableList.add("cherry"); // UnsupportedOperationException } }
在這個(gè)例子中,我們首先創(chuàng)建了一個(gè)可修改的 ArrayList,然后使用 Collections.unmodifiableList() 方法將其轉(zhuǎn)換為不可修改的集合。如果嘗試修改這個(gè)不可變集合(例如調(diào)用 add() 或 remove() 方法),則會(huì)拋出 UnsupportedOperationException 異常。
2.2. 使用 Java 9 引入的 List.of()、Set.of() 和 Map.of() 方法
從 Java 9 開(kāi)始,Java 引入了一些便捷的方法來(lái)創(chuàng)建不可變集合:
List.of()
:創(chuàng)建不可變的列表。Set.of()
:創(chuàng)建不可變的集合。Map.of()
:創(chuàng)建不可變的映射。
這些方法創(chuàng)建的集合是不可修改的,并且具有性能優(yōu)化,適合快速創(chuàng)建不可變集合。
import java.util.*; public class ImmutableExample { public static void main(String[] args) { // 創(chuàng)建不可變列表 List<String> immutableList = List.of("apple", "banana", "cherry"); // 創(chuàng)建不可變集合 Set<String> immutableSet = Set.of("apple", "banana", "cherry"); // 創(chuàng)建不可變映射 Map<String, Integer> immutableMap = Map.of("apple", 1, "banana", 2); // 嘗試修改集合會(huì)拋出異常 // immutableList.add("orange"); // UnsupportedOperationException // immutableSet.add("orange"); // UnsupportedOperationException // immutableMap.put("orange", 3); // UnsupportedOperationException } }
在這個(gè)例子中,我們使用了 List.of()、Set.of() 和 Map.of() 來(lái)創(chuàng)建不可變集合。它們的主要優(yōu)點(diǎn)是能夠一次性創(chuàng)建不可變集合并且語(yǔ)法簡(jiǎn)潔。
2.3. 使用 ImmutableList、ImmutableSet 和 ImmutableMap(Guava)
Guava 是 Google 提供的一個(gè) Java 庫(kù),提供了一些更加豐富的不可變集合類(lèi)。通過(guò) ImmutableList、ImmutableSet 和 ImmutableMap,我們可以非常方便地創(chuàng)建不可變集合。
import com.google.common.collect.*; public class ImmutableExample { public static void main(String[] args) { // 創(chuàng)建不可變的 List ImmutableList<String> immutableList = ImmutableList.of("apple", "banana", "cherry"); // 創(chuàng)建不可變的 Set ImmutableSet<String> immutableSet = ImmutableSet.of("apple", "banana", "cherry"); // 創(chuàng)建不可變的 Map ImmutableMap<String, Integer> immutableMap = ImmutableMap.of("apple", 1, "banana", 2); // 嘗試修改集合會(huì)拋出異常 // immutableList.add("orange"); // UnsupportedOperationException // immutableSet.add("orange"); // UnsupportedOperationException // immutableMap.put("orange", 3); // UnsupportedOperationException } }
在這個(gè)例子中,ImmutableList、ImmutableSet 和 ImmutableMap 提供了一個(gè)非常方便的 API 來(lái)創(chuàng)建不可變集合。與 Collections.unmodifiableXXX() 不同,Guava 的不可變集合是專(zhuān)門(mén)設(shè)計(jì)的,可以提供更好的性能和更高的靈活性。
2.4. 使用 Record 創(chuàng)建不可變集合(Java 16+)
從 Java 16 開(kāi)始,Java 引入了 Record 類(lèi)型,它是一個(gè)不可變的類(lèi),用于存儲(chǔ)數(shù)據(jù)。雖然 Record 主要用于創(chuàng)建不可變的對(duì)象,但它也可以配合集合類(lèi)型使用,來(lái)保證集合內(nèi)容的不可變性。
import java.util.*; public class ImmutableRecordExample { public static void main(String[] args) { // 使用 Record 類(lèi) record Fruit(String name, int quantity) {} List<Fruit> fruits = List.of(new Fruit("apple", 5), new Fruit("banana", 3)); // fruits 是不可變的,元素不可修改 // fruits.add(new Fruit("orange", 2)); // UnsupportedOperationException } }
Record
類(lèi)型是不可變的,這意味著一旦創(chuàng)建就不能更改其字段。因此,可以使用 Record
類(lèi)型來(lái)表示集合中的數(shù)據(jù)對(duì)象,從而保證對(duì)象本身的不可變性。
3. 不可變集合的優(yōu)勢(shì)
不可變集合相對(duì)于可變集合,有以下幾個(gè)顯著的優(yōu)勢(shì):
- 線程安全:不可變集合是線程安全的,因?yàn)槠鋬?nèi)容在創(chuàng)建之后不可更改。多個(gè)線程可以同時(shí)訪問(wèn)而不會(huì)發(fā)生并發(fā)修改的問(wèn)題。
- 性能優(yōu)化:不可變集合避免了同步和加鎖操作,可以減少線程間的競(jìng)爭(zhēng)和同步開(kāi)銷(xiāo),適合高并發(fā)場(chǎng)景。
- 數(shù)據(jù)一致性:不可變集合能保證數(shù)據(jù)的一致性,避免了集合中的數(shù)據(jù)在程序運(yùn)行過(guò)程中被意外修改。
- 簡(jiǎn)化代碼:不可變集合的設(shè)計(jì)簡(jiǎn)化了程序代碼,因?yàn)椴恍枰紤]修改操作,也不需要額外的同步處理。
4. 不可變集合的劣勢(shì)
當(dāng)然,不可變集合也有一定的劣勢(shì):
- 靈活性差:一旦創(chuàng)建了不可變集合,就不能對(duì)其中的數(shù)據(jù)進(jìn)行修改。如果需要修改集合內(nèi)容,需要?jiǎng)?chuàng)建新的集合,可能會(huì)增加一定的內(nèi)存開(kāi)銷(xiāo)。
- 性能問(wèn)題:對(duì)于頻繁修改集合的場(chǎng)景,使用不可變集合可能導(dǎo)致性能下降,因?yàn)槊看涡薷亩紩?huì)創(chuàng)建新的集合實(shí)例。
5. 總結(jié)
不可變集合在多線程環(huán)境下具有顯著的優(yōu)勢(shì),因?yàn)樗鼈兲焐蔷€程安全的,不需要同步控制。Java 提供了多種實(shí)現(xiàn)不可變集合的方式,包括 Collections.unmodifiableXXX()、List.of()、Set.of()、Map.of()、Guava 提供的不可變集合等。在使用不可變集合時(shí),開(kāi)發(fā)者應(yīng)根據(jù)具體的需求,權(quán)衡其帶來(lái)的性能優(yōu)化和內(nèi)存開(kāi)銷(xiāo)。
無(wú)論是在并發(fā)編程中還是在單線程應(yīng)用中,適當(dāng)使用不可變集合能夠顯著提高代碼的健壯性、性能和可維護(hù)性。
到此這篇關(guān)于Java中不可變集合的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)Java實(shí)現(xiàn)不可變集合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實(shí)例分析java中重載與重寫(xiě)的區(qū)別
這篇文章主要介紹了實(shí)例分析java中重載與重寫(xiě)的區(qū)別,需要的朋友可以參考下2014-07-07Java使用正則表達(dá)式(regex)匹配中文實(shí)例代碼
本文給大家分享java使用正則表達(dá)式匹配中文的實(shí)例代碼,以及java中要匹配中文的正則表達(dá)式兩種寫(xiě)法,感興趣的朋友通過(guò)本文一起看看吧2016-12-12淺談spring的重試機(jī)制無(wú)效@Retryable@EnableRetry
這篇文章主要介紹了淺談spring的重試機(jī)制無(wú)效@Retryable@EnableRetry,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(38)
下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你2021-07-07Java的JSON轉(zhuǎn)換類(lèi)庫(kù)GSON的基礎(chǔ)使用教程
GSON是谷歌開(kāi)源的一款Java對(duì)象與JSON對(duì)象互相轉(zhuǎn)換的類(lèi)庫(kù),Java的JSON轉(zhuǎn)換類(lèi)庫(kù)GSON的基礎(chǔ)使用教程,需要的朋友可以參考下2016-06-06MyBatis 實(shí)現(xiàn)批量插入和刪除中雙層循環(huán)的寫(xiě)法案例
這篇文章主要介紹了MyBatis 實(shí)現(xiàn)批量插入和刪除中雙層循環(huán)的寫(xiě)法案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01SpringBoot?Web請(qǐng)求響應(yīng)詳細(xì)代碼示例
在Web開(kāi)發(fā)中請(qǐng)求和響應(yīng)是必不可少的環(huán)節(jié),Spring Boot Web應(yīng)用中請(qǐng)求響應(yīng)的分層解耦是構(gòu)建高效、可維護(hù)系統(tǒng)的關(guān)鍵實(shí)踐,下面這篇文章主要介紹了SpringBoot?Web請(qǐng)求響應(yīng)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09