1. 程式人生 > >還在使用集合類完成這些功能?不妨來看看 Guava 集合類!!!

還在使用集合類完成這些功能?不妨來看看 Guava 集合類!!!

>博文地址: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