自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

跟著 Guava 學(xué) Java 之 不可變集合

開發(fā) 后端
不可變集合,英文叫 immutable,顧名思義就是說集合是不可被修改的。集合的數(shù)據(jù)項(xiàng)是在創(chuàng)建的時(shí)候提供,并且在整個(gè)生命周期中都不可改變。

什么是不可變集合

不可變集合,英文叫 immutable,顧名思義就是說集合是不可被修改的。集合的數(shù)據(jù)項(xiàng)是在創(chuàng)建的時(shí)候提供,并且在整個(gè)生命周期中都不可改變。

為什么要用不可變集合?

第一:防御性編程需要

我有一個(gè)集合,你拿來使用,鬼知道你會(huì)不會(huì)亂搞,往集合里添加不合適的元素,或者隨便刪除元素,我不放心,對,就是不信你,我的集合我做主,給你個(gè)不可變的吧,這樣你就不可能亂搞我的集合了,我就放心了,不擔(dān)心你的操作給我?guī)盹L(fēng)險(xiǎn) 。官方解釋:防御,defensive programming,聽起來高級不?

第二:線程安全

沒有買賣就沒有殺害!

集合是不可變的,不讓你有變化,不可能有變化。沒有變化,就沒有競態(tài)條件,多少個(gè)線程來都是一個(gè)樣,安全,就是***安全。

第三:節(jié)省開銷

不需要支持可變性,可以盡量節(jié)省空間和時(shí)間的開銷, 所有的不可變集合實(shí)現(xiàn)都比可變集合更加有效的利用內(nèi)存。

JDK9 之前的實(shí)現(xiàn)

Collections提供了一組方法把可變集合封裝成不可變集合:

圖片

但這玩意兒有問題,舉個(gè)例子:

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

List<String> unmodifiableList = Collections.unmodifiableList(list);
list.add("d");
System.out.println(unmodifiableList);

這個(gè)輸出的結(jié)果居然是 [a,b,c,d]。

what ? 這不就變了嗎,我要的是不可變集合啊,這坑爹的玩意兒。有兄弟說了,那我切斷 list 的引用是不就行了?

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

List<String> unmodifiableList = Collections.unmodifiableList(list);
list.add("d");
list = null;
System.out.println(unmodifiableList);

呵呵,不行,輸出仍然是  [a,b,c,d]  果然坑爹,而且你發(fā)現(xiàn)沒有,編碼也比較麻煩,還得用 Collections 間接轉(zhuǎn)一下。

Collections.unmodifiableList 實(shí)現(xiàn)的不是真正的不可變集合,當(dāng)原始集合修改后,不可變集合也發(fā)生變化。此外,它返回的數(shù)據(jù)結(jié)構(gòu)本質(zhì)仍舊是原來的集合類,所以它的操作開銷,包括并發(fā)下修改檢查,hash table 里的額外數(shù)據(jù)空間都和原來的集合是一樣的。

由于這些問題,JDK9 出了些新的生成不可變集合的方法,比如:

  • List.of
  • Set.of
  • Map.of
  • ......

確實(shí)可以直接生成不可變集合,編碼也比較方便了:

List<String> immutableList= List.of("a", "b", "c");

如果你要修改集合會(huì)拋出異常 java.lang.UnsupportedOperationException:

immutableList.add("d");

but;

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

List<List<String>> list1 = List.of(list);
list.add("d");
System.out.println(list1);

上面代碼的輸出仍然是 : [a,b,c,d];

當(dāng)然我們不是說人家 api 是錯(cuò)的,人家就是這么設(shè)計(jì)的(愛信不信),可我感覺不爽,如果不小心可能會(huì)犯錯(cuò),本來是防御性編程,搞不好干成跑路性編程了。

再次強(qiáng)調(diào),不是說人家 JDK 設(shè)計(jì)錯(cuò)了,人家就是這么設(shè)計(jì)的,你的明白?當(dāng)然不爽的還有 google 的工程師們,所以我們下面介紹下拿起鍵盤自己解決問題的 google 工程師們寫的 guava 是怎么解決問題的。

Guava

來,我們接著上面的那個(gè)例子,直接寫個(gè) Guava 版本的你自己體會(huì)下:

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

ImmutableList<String> strings = ImmutableList.copyOf(list);
list.add("d");

System.out.println(strings);

輸出終于如我所愿的是 : [a,b,c] 了。

無論是從命名、語義、結(jié)果、代碼可讀性是不是都比 JDK 版本的好很多?這樣的代碼讓我感覺世界又美好了一些。

美好的東西都想擁有,但問題來了, Guava 針對哪些集合提供了哪些對應(yīng)的不可變集合類呢,這里我們給大家整理了一下:

可變集合接口

屬于 JDK 還是 Guava

不可變版本

Collection

JDK

ImmutableCollection

List

JDK

ImmutableList

Set

JDK

ImmutableSet

SortedSet/NavigableSet

JDK

ImmutableSortedSet

Map

JDK

ImmutableMap

SortedMap

JDK

ImmutableSortedMap

Multiset

Guava

ImmutableMultiset

SortedMultiset

Guava

ImmutableSortedMultiset

Multimap

Guava

ImmutableMultimap

ListMultimap

Guava

ImmutableListMultimap

SetMultimap

Guava

ImmutableSetMultimap

BiMap

Guava

ImmutableBiMap

ClassToInstanceMap

Guava

ImmutableClassToInstanceMap

Table

Guava

ImmutableTable

介紹幾個(gè)方法:

  • of 方法,用法是一脈相承的,就是構(gòu)建集合用的
  • copyOf ,上面例子中出現(xiàn)過,官方文檔上說它是智能的,比如它可以判斷參數(shù)是不是一個(gè) immutable 對象,這樣可以避免做拷貝

JDK10

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

List<String> strings = List.copyOf(list);

list.add("d");
System.out.println(strings);

以上代碼在 JDK10 以上版本輸出  :[a,b,c],主要是因?yàn)?copyOf 方法是 10 以上版本才有的。

你看,JDK 也一直在進(jìn)步,所以如果你用的是 JDK10 以及上版本,是不是要用 Guava 在這個(gè)具體功能點(diǎn)上就是可選的了。

最后

整體對比起來,我的個(gè)人感覺是在不可變集合的操作上 Guava 的 API 更好用一些,當(dāng)然庫的使用因人而異,用 JDK 原生的也沒毛病,畢竟依賴更少,學(xué)習(xí)成本也小。

我們總說要改革、要進(jìn)步,而真正的改革往往都不是自上而下的,很多都是自下而上的被推動(dòng)著前進(jìn) ,如果沒有 Guava,沒有開源社區(qū)的很多優(yōu)秀的庫和組件,JDK 會(huì)不會(huì)把這些優(yōu)秀的建議吸取進(jìn)來?我不知道,但至少 JAVA 也一直在進(jìn)步,也希望它越來越好。

責(zé)任編輯:武曉燕 來源: 小盒子的技術(shù)分享
相關(guān)推薦

2023-10-20 08:18:17

Python數(shù)據(jù)類型

2022-02-09 07:52:36

GolangGo語言

2022-09-21 08:16:18

緩存框架

2022-08-19 19:02:20

開源鴻蒙操作系統(tǒng)

2023-06-07 19:17:14

UbuntuKDELinux

2024-02-26 10:47:09

Python數(shù)據(jù)類型開發(fā)

2024-04-08 07:58:11

Python數(shù)據(jù)類型字符串

2010-01-14 14:30:09

VB.NET匿名類型

2015-10-12 08:56:27

Java不可變

2015-03-19 15:04:06

2022-06-28 09:10:32

K8S容器鏡像滾動(dòng)升級

2023-02-18 13:47:04

CoreOS容器操作系統(tǒng)云原生

2017-04-02 09:30:15

機(jī)器人駕校機(jī)器人教學(xué)

2021-06-14 09:34:23

對象存儲(chǔ)存儲(chǔ)

2022-02-07 10:21:54

.NET配置對象

2020-03-09 10:21:12

Java集合類 Guava

2022-08-29 17:25:19

鴻蒙應(yīng)用開發(fā)

2025-02-08 13:23:27

JavaScript開發(fā)喚醒鎖

2021-04-07 17:06:55

String Final存儲(chǔ)

2024-09-24 08:36:18

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號