還在使用集合類完成這些功能?不妨來看看 Guava 集合類!!!
阿新 • • 發佈:2020-03-13
>博文地址:https://sourl.cn/CXgw9P
日常開發中,小黑哥經常需要用到 Java 提供集合類完成各種需求。Java 集合類雖然非常強大實用,但是提供功能還是有點薄弱。
舉個例子,小黑哥最近接到一個需求,從輸入一個文件中,統計一個關鍵詞出現的次數。程式碼如下:
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073808852-1209478404.jpg)
雖然這個需求使用 `Map` 可以輕鬆搞定,但是小黑哥還是覺得這種寫法有點笨拙,如果沒有判空,將會導致 NPE 異常。
如果很多地方需要功能,我們就可以抽象出來,將其封裝成工具類。
不過上面的功能大家就不需要自己封裝,一款來自 **Google** 開源工具類-**Guava**,可以輕鬆的解決上面的統計問題。
## Guava 介紹
Guava 是一款 Google 開源工具類,包含許多 Google 內部 `Java` 專案依賴的核心類。Guava 擴充套件 Java 基礎類工程,比如集合,併發等,也增加一些其他強大功能,比如快取,限流等功能。
另外 Guava 推出一些類,如 `Optional`,甚至被 Java 開發者學習,後續增加到 JDK 中。
目前 [Guava Github 倉庫](https://github.com/google/guava)已有 **36k star**,可以見到 Guava 受歡迎程度。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809050-324423312.jpg)
Guava 核心功能包括多個模組,今天小黑哥主要帶大家玩轉 Guava 集合類。
## 擴充套件集合類
Guava 創造很多 JDK 沒有,但是我們日常卻明顯有用的新集合型別。這些新型別使用 JDK 集合介面規範,所以使用方法與 JDK 集合框架差不多,並沒有增加很多使用難度。
### Multiset
小黑哥第一次見到 `Multiset` 這個類,還以為是 `Set` 介面子類。實際上此『Set』,僅僅只是數學上集合概念。
`Multiset` 繼承 JDK `Collection` 介面,我們可以多次增加相同的元素,另外 `Multiset` 最大特定將會為元素計數,我們可以將它類似等同為 `Map` 。
使用 `Multiset`可以輕鬆解決開頭的問題。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809183-1587978442.jpg)
使用 `Multiset` 簡化了程式碼,並且再也不用擔心新 **NPE** 的問題。
跟 JDK 集合類一樣,`Multiset`也有許多子類。
![來源於 Github](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809294-232108898.jpg)
這裡小黑哥提醒一下大家,雖然上面說過我們可以將 `Multiset` 看做 `Map`,但是 `Multiset` 可不是 `Map` 的子類,它可是 血統純正的 `Collection` 子類。
### Multimap
小黑哥有時會在業務需求中使用 `Map `實現下面的需求。
```jav
a->[1,2,3] b->4,c->[6,5]
```
使用 `Map` + `List` 這種結構比較笨拙,並且程式碼實現也比較繁瑣。`Multimap` 正式 Guava 中解決這種問題的新出的一個雷。
使用 `Multimap` 實現程式碼如下:
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809404-140991873.jpg)
這裡小黑哥使用 `Multimap` 子類 `HashMultimap`,其行為類似為 `Map>`,也就是說 `Value` 對應的集合內部元素不能重複。如果需要儲存的重複的元素我們可以使用 `ArrayListMultimap`。
`Multimap`還有其他子類,如圖所示:
![來源於 Github](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809552-517452346.jpg)
### BiMap
`BiMap` 可以用來實現鍵值對的雙向對映需求,這樣我們就可以通過 `Key` 查詢對對應的 `Value`,也可以使用 `Value` 查詢對應的 `Key`。
這個需求如果使用 `Map` 實現,我們就不得不使用兩個 `Map`,維護雙向關係,並且任何改動還要保持同步。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809700-845831701.jpg)
使用 `BiMap` 修改上面的程式碼:
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809808-1646676550.jpg)
這裡需要注意,`BiMap#put`方法不能加入重複元素, 若加入,將會拋錯。如果若特定值一定要替換,可以使用 `BiMap#forcePut`代替。
敲黑板,這個知識點記下來。小黑哥使用過程中,就踩過這個坑。
同樣的 `BiMap` 也有各種實現類:
![來源於 Github](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073809948-1969882288.jpg)
### 其他擴充套件集合類
Guava 另外還提供其他集合類,不過這些類使用起來有點複雜,小黑哥還未在業務程式碼中使用過,這裡簡單提下,感興趣同學可以深入瞭解一下。
- Table
- ClassToInstanceMap
- RangeSet
- RangeMap
## 集合工具類
除了上面提到的新集合類以外,Guava 提供通用的工具類:
![來源於 Github](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810081-607737181.jpg)
這些工具類需對使用的方法,我們可以快速建立集合,分割集合,轉化集合等。
### 快速建立集合例項
使用工具類,我們可以快速建立集合。例如:
```java
List list=Lists.newArrayList();
Set set=Sets.newHashSet();
Map map=Maps.newHashMap();
```
相比於 `new` 集合方法,Guava 方法建立方式更加簡單。
```java
List list=new ArrayList();
Set set=new HashSet();
Map map=new HashMap();
```
Guava 工具類智慧推導 `List` 泛型,再也不用兩側都重複寫泛型了。
另外還可以指定集合類的初始化大小。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810258-122686511.jpg)
### Lists.transform
`Lists#transform`方法可以替代繁瑣 `for` 迴圈,將元素轉化,建立一個新集合類。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810405-644226866.jpg)
不過使用這個方法我們要**注意**一點。
`Lists#transform` 內部使用懶載入的機制,只有在呼叫獲取的元素的時候,如 `result.get` 才會真正使用 `Function` 從源 `List` 獲取元素,做相應的轉化。**每次獲取元素**都將會使用 `function` 進行轉化。
所以使用 `Lists#transform` 得到 `List` 僅僅只是源 `List` 一個檢視,任何對源 `List` 的元素修改,都將會被反應到建立之後的 `List` 。任何對建立之後 List 中的元素進行修改,都不會生效。下次再次讀取元素時,將會發現相應修改的丟失了。。。
小黑哥之前就踩過這個坑,如果你有這種需求,可以使用以下方式建立一個新集合:
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810525-1110036160.jpg)
> JDK8 之前版本,小黑哥經常使用該方法轉化 `List` 中的元素。不過你如果使用 JDK8,小黑哥還是推薦使用 Stream 流式程式設計。
### 交集並集差集
`Sets` 提供幾個方法,可以快速求出兩個 `Set` 集合的交集,並集以及差集。
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810714-929651750.png)
## 不可變集合
不可變(**Immutable**)集合,顧名思義集合不可以被修改。初始建立不可變集合時嗎,需要傳入資料來源,建立完成之後,集合就再也不能修改,增加,刪除元素,否則將會報錯。
這是一種防禦性策略,防止集合在後續操作中被修改,從而引發問題。
不可變集合優點在於:
- 由於不可變集合僅僅只能讀,多執行緒併發天然安全
- 由於不可變集合固定不變,可以將其當做常量安全,不用單線其他人修改
- 不可變集合佔用更少記憶體空間
- 不可變集合不可以被修改,所以不用擔心其他程式任意修改集合
Guava 不可變集合支援 JDK 所有集合介面:
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810852-2062921527.jpg)
我們可以使用如下幾種方式建立不可變集合,以 `ImmutableList` 為例:
![ImmutableList](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073810997-1689931186.jpg)
```java
List fromList=Lists.newArrayList("點贊","關注");
// 從一個集合拷貝元素
ImmutableList.copyOf(fromList);
ImmutableList.of("關注","Java極客技術");
ImmutableList.builder().add("關注").addAll(fromList).build();
```
## 總結
這篇文章小黑哥帶大家學習開源工具 Guava 集合的相關類使用方法,日常開發中我們善於使用這些工具類,不要自己重複造輪子。
本篇文章僅僅只是介紹 Guava 一小部分功能,還有很對功能,小黑哥也覺得很好用在。這裡推薦大家去檢視 Guava 官方 wiki,檢視具體使用方法。
如果大家還想知道其他開源工具類,給小黑哥**點個贊**,下次給大家帶來十分好用開源工具類~
![](https://img2020.cnblogs.com/other/1419561/202003/1419561-20200313073811119-1291858101.jpg)
> 歡迎關注我的公眾號:程式通事,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關注我的部落格:[studyidea.cn](https://studyi