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

日常開發中,小黑哥經常需要用到 Java 提供集合類完成各種需求。Java 集合類雖然非常強大實用,但是提供功能還是有點薄弱。

舉個例子,小黑哥最近接到一個需求,從輸入一個文檔中,統計一個關鍵詞出現的次數。代碼如下:

雖然這個需求使用 Map 可以輕鬆搞定,但是小黑哥還是覺得這種寫法有點笨拙,如果沒有判空,將會導致 NPE 異常。

如果很多地方需要功能,我們就可以抽象出來,將其封裝成工具類。

不過上面的功能大家就不需要自己封裝,一款來自 Google 開源工具類-Guava,可以輕鬆的解決上面的統計問題。

Guava 介紹

Guava 是一款 Google 開源工具類,包含許多 Google 內部 Java 項目依賴的核心類。Guava 擴展 Java 基礎類工程,比如集合,併發等,也增加一些其他強大功能,比如緩存,限流等功能。

另外 Guava 推出一些類,如 Optional,甚至被 Java 開發者學習,後續增加到 JDK 中。

目前 Guava Github 倉庫已有 36k star,可以見到 Guava 受歡迎程度。

Guava 核心功能包括多個模塊,今天小黑哥主要帶大家玩轉 Guava 集合類。

擴展集合類

Guava 創造很多 JDK 沒有,但是我們日常卻明顯有用的新集合類型。這些新類型使用 JDK 集合接口規範,所以使用方法與 JDK 集合框架差不多,並沒有增加很多使用難度。

Multiset

小黑哥第一次見到 Multiset 這個類,還以爲是 Set 接口子類。實際上此『Set』,僅僅只是數學上集合概念。

Multiset 繼承 JDK Collection 接口,我們可以多次增加相同的元素,另外 Multiset 最大特定將會爲元素計數,我們可以將它類似等同爲 Map<E, Integer>

使用 Multiset可以輕鬆解決開頭的問題。

使用 Multiset 簡化了代碼,並且再也不用擔心新 NPE 的問題。

跟 JDK 集合類一樣,Multiset也有許多子類。

來源於 Github

這裏小黑哥提醒一下大家,雖然上面說過我們可以將 Multiset<E> 看做 Map<E, Integer>,但是 Multiset 可不是 Map 的子類,它可是 血統純正的 Collection 子類。

Multimap

小黑哥有時會在業務需求中使用 Map<String,List<Integer>實現下面的需求。

a->[1,2,3] b->4,c->[6,5]

使用 Map + List 這種結構比較笨拙,並且代碼實現也比較繁瑣。Multimap 正式 Guava 中解決這種問題的新出的一個雷。

使用 Multimap 實現代碼如下:

這裏小黑哥使用 Multimap 子類 HashMultimap,其行爲類似爲 Map<K,Set<V>>,也就是說 Value 對應的集合內部元素不能重複。如果需要保存的重複的元素我們可以使用 ArrayListMultimap

Multimap還有其他子類,如圖所示:

來源於 Github

BiMap

BiMap 可以用來實現鍵值對的雙向映射需求,這樣我們就可以通過 Key 查找對對應的 Value,也可以使用 Value 查找對應的 Key

這個需求如果使用 Map 實現,我們就不得不使用兩個 Map,維護雙向關係,並且任何改動還要保持同步。

使用 BiMap 修改上面的代碼:

這裏需要注意,BiMap#put方法不能加入重複元素, 若加入,將會拋錯。如果若特定值一定要替換,可以使用 BiMap#forcePut代替。

敲黑板,這個知識點記下來。小黑哥使用過程中,就踩過這個坑。

同樣的 BiMap 也有各種實現類:

來源於 Github

其他擴展集合類

Guava 另外還提供其他集合類,不過這些類使用起來有點複雜,小黑哥還未在業務代碼中使用過,這裏簡單提下,感興趣同學可以深入瞭解一下。

  • Table
  • ClassToInstanceMap
  • RangeSet
  • RangeMap

集合工具類

除了上面提到的新集合類以外,Guava 提供通用的工具類:

來源於 Github

這些工具類需對使用的方法,我們可以快速創建集合,分割集合,轉化集合等。

快速創建集合實例

使用工具類,我們可以快速創建集合。例如:

List<String> list=Lists.newArrayList();
Set<String> set=Sets.newHashSet();
Map<String,String> map=Maps.newHashMap();

相比於 new 集合方法,Guava 方法創建方式更加簡單。

List<String> list=new ArrayList<String>();
Set<String> set=new HashSet<String>();
Map<String,String> map=new HashMap<String, String>();

Guava 工具類智能推導 List 泛型,再也不用兩側都重複寫泛型了。

另外還可以指定集合類的初始化大小。

Lists.transform

Lists#transform方法可以替代繁瑣 for 循環,將元素轉化,創建一個新集合類。

不過使用這個方法我們要注意一點。

Lists#transform 內部使用懶加載的機制,只有在調用獲取的元素的時候,如 result.get 纔會真正使用 Function 從源 List 獲取元素,做相應的轉化。每次獲取元素都將會使用 function 進行轉化。

所以使用 Lists#transform 得到 List 僅僅只是源 List 一個視圖,任何對源 List 的元素修改,都將會被反應到創建之後的 List 。任何對創建之後 List 中的元素進行修改,都不會生效。下次再次讀取元素時,將會發現相應修改的丟失了。。。

小黑哥之前就踩過這個坑,如果你有這種需求,可以使用以下方式創建一個新集合:

JDK8 之前版本,小黑哥經常使用該方法轉化 List 中的元素。不過你如果使用 JDK8,小黑哥還是推薦使用 Stream 流式編程。

交集並集差集

Sets 提供幾個方法,可以快速求出兩個 Set 集合的交集,並集以及差集。

不可變集合

不可變(Immutable)集合,顧名思義集合不可以被修改。初始創建不可變集合時嗎,需要傳入數據源,創建完成之後,集合就再也不能修改,增加,刪除元素,否則將會報錯。

這是一種防禦性策略,防止集合在後續操作中被修改,從而引發問題。

不可變集合優點在於:

  • 由於不可變集合僅僅只能讀,多線程併發天然安全
  • 由於不可變集合固定不變,可以將其當做常量安全,不用單線其他人修改
  • 不可變集合佔用更少內存空間
  • 不可變集合不可以被修改,所以不用擔心其他程序任意修改集合

Guava 不可變集合支持 JDK 所有集合接口:

我們可以使用如下幾種方式創建不可變集合,以 ImmutableList 爲例:

ImmutableList

List<String> fromList=Lists.newArrayList("點贊","關注");
// 從一個集合拷貝元素
ImmutableList.copyOf(fromList);
ImmutableList.of("關注","Java極客技術");
ImmutableList.builder().add("關注").addAll(fromList).build();

總結

這篇文章小黑哥帶大家學習開源工具 Guava 集合的相關類使用方法,日常開發中我們善於使用這些工具類,不要自己重複造輪子。

本篇文章僅僅只是介紹 Guava 一小部分功能,還有很對功能,小黑哥也覺得很好用在。這裏推薦大家去查看 Guava 官方 wiki,查看具體使用方法。

如果大家還想知道其他開源工具類,給小黑哥點個贊,下次給大家帶來十分好用開源工具類~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章