為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

點擊上方 "程序員小樂"關注, 星標或置頂一起成長

每天凌晨00點00分, 第一時間與你相約


每日英文

Themorewefind,themorewelose.Themoreweknow,themorewehurt.Themorewecare,themorewearesad.

得到越多,失去越多。懂得越多,傷得越多。在乎越多,難過越多。


每日掏心話

如果你越來越冷漠,你以為你成長了,但其實沒有。長大應該是變溫柔,對全世界都溫柔。


鏈接:jianshu.com/p/97778b21bd00

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?
程序員小樂(ID:study_tech)第 821 次推文 圖片來自百度


往日回顧:微信技術總監:一億用戶背後的架構秘密


00 前言


阿里巴巴出了一本Java規範,在國內java開發眼裡被賦予了神聖的殿堂,我不推薦你用阿里巴巴的開發手冊。目前Google Guava在實際應用中非常廣泛,本篇博客將以博主對 Guava 使用的認識以及在項目中的經驗來給大家分享!學習使用 Google Guava可以讓你快樂編程,寫出優雅的 Java 代碼,在業務允許的條件下,我推薦使用 Guava編程!Google 出品 Java 編碼規範,科學又權威,強烈推薦!


01 正文

Joiner/Splitter/CharMatcherJDK提供的String還不夠好麼?也許還不夠友好,至少讓我們用起來還不夠爽,還得操心!舉個栗子,比如String提供的split方法,我們得關心空字符串吧,還得考慮返回的結果中存在null元素吧,只提供了前後trim的方法(如果我想對中間元素進行trim呢)。那麼,看下面的代碼示例,guava讓你不必在操心這些:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

Joiner是連接器,Splitter是分割器,通常我們會把它們定義為static final,利用on生成對象後在應用到String進行處理,這是可以複用的。要知道apache commons StringUtils提供的都是static method。更加重要的是,guava提供的Joiner/Splitter是經過充分測試,它的穩定性和效率要比apache高出不少,這個你可以自行測試下。發現沒有我們想對String做什麼操作,就是生成自己定製化的Joiner/Splitter,多麼直白,簡單,流暢的API!對於Joiner,常用的方法是 跳過NULL元素:skipNulls() / 對於NULL元素使用其他替代:useForNull(String)對於Splitter,常用的方法是:trimResults()/omitEmptyStrings()。注意拆分的方式,有字符串,還有正則,還有固定長度分割(太貼心了!)其實除了Joiner/Splitter外,guava還提供了字符串匹配器:CharMatcher

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

CharMatcher,將字符的匹配和處理解耦,並提供豐富的方法供你使用!對基本類型的支持guava對JDK提供的原生類型操作進行了擴展,使得功能更加強大

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

guava提供了Bytes/Shorts/Ints/Iongs/Floats/Doubles/Chars/Booleans這些基本數據類型的擴展支持,只有你想不到的,沒有它沒有的!對 JDK 的有效補充灰色地帶:MultisetJDK的集合,提供了有序且可以重複的List,無序且不可以重複的Set。那這裡其實對於集合涉及到了2個概念,一個order,一個dups。那麼List vs Set,and then some ?


為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

MultisetMultiset是什麼,我想上面的圖,你應該瞭解它的概念了。Multiset就是無序的,但是可以重複的集合,它就是遊離在List/Set之間的“灰色地帶”!(至於有序的,不允許重複的集合嘛,guava還沒有提供,當然在未來應該會提供UniqueList,我猜的,哈哈)來看一個Multiset的示例:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

Multiset自帶一個有用的功能,就是可以跟蹤每個對象的數量。

Immutable vs unmodifiable

來我們先看一個unmodifiable的例子:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

你看到JDK提供的unmodifiable的缺陷了嗎?實際上,Collections.unmodifiableXxx所返回的集合和源集合是同一個對象,只不過可以對集合做出改變的API都被override,會拋出UnsupportedOperationException。也即是說我們改變源集合,導致不可變視圖(unmodifiable View)也會發生變化,oh my god!當然,在不使用guava的情況下,我們是怎麼避免上面的問題的呢?

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

上面揭示了一個概念:Defensive Copies,保護性拷貝。OK,unmodifiable看上去沒有問題呢,但是guava依然覺得可以改進,於是提出了Immutable的概念,來看:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

就一個copyOf,你不會忘記,如此cheap用Google官方的說法是:we're using just one class,just say exactly what we mean,很了不起嗎(不僅僅是個概念,Immutable在COPY階段還考慮了線程的併發性等,很智能的!)guava提供了很多Immutable集合,比如ImmutableList/ImmutableSet/ImmutableSortedSet/ImmutableMap/......看一個ImmutableMap的例子:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

可不可以一對多:Multimap
JDK提供給我們的Map是一個鍵,一個值,一對一的,那麼在實際開發中,顯然存在一個KEY多個VALUE的情況(比如一個分類下的書本),我們往往這樣表達:Map>,好像有點臃腫!臃腫也就算了,更加不爽的事,我們還得判斷KEY是否存在來決定是否new 一個LIST出來,有點麻煩!更加麻煩的事情還在後頭,比如遍歷,比如刪除,so hard......來看guava如何替你解決這個大麻煩的:

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

友情提示下,guava所有的集合都有create方法,這樣的好處在於簡單,而且我們不必在重複泛型信息了。
get()/keys()/keySet()/values()/entries()/asMap()都是非常有用的返回view collection的方法。Multimap的實現類有:ArrayListMultimap/HashMultimap/LinkedHashMultimap/TreeMultimap/ImmutableMultimap/......

可不可以雙向:BiMap

JDK提供的MAP讓我們可以find value by key,那麼能不能通過find key by value呢,能不能KEY和VALUE都是唯一的呢。這是一個雙向的概念,即forward+backward。在實際場景中有這樣的需求嗎?比如通過用戶ID找到mail,也需要通過mail找回用戶名。沒有guava的時候,我們需要create forward map AND create backward map,and now just let guava do that for you.

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

biMap / biMap.inverse() / biMap.inverse().inverse() 它們是什麼關係呢?你可以稍微看一下BiMap的源碼實現,實際上,當你創建BiMap的時候,在內部維護了2個map,一個forward map,一個backward map,並且設置了它們之間的關係。因此,biMap.inverse() != biMap ;biMap.inverse().inverse() == biMap

可不可以多個KEY:Table

我們知道數據庫除了主鍵外,還提供了複合索引,而且實際中這樣的多級關係查找也是比較多的,當然我們可以利用嵌套的Map來實現:Map>。為了讓我們的代碼看起來不那麼醜陋,guava為我們提供了Table。

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

Table涉及到3個概念:rowKey,columnKey,value,並提供了多種視圖以及操作方法讓你更加輕鬆的處理多個KEY的場景。函數式編程:Funcitons

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

上面的代碼是為了完成將List集合中的元素,先截取5個長度,然後轉成大寫。函數式編程的好處在於在集合遍歷操作中提供自定義Function的操作,比如transform轉換。我們再也不需要一遍遍的遍歷集合,顯著的簡化了代碼!

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

對集合的transform操作可以通過Function完成斷言:PredicatePredicate最常用的功能就是運用在集合的過濾當中!

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

需要注意的是Lists並沒有提供filter方法,不過你可以使用Collections2.filter完成!

check null and other:Optional、Preconditions

在guava中,對於null的處理手段是快速失敗,你可以看看guava的源碼,很多方法的第一行就是:Preconditions.checkNotNull(elements);

要知道null是模糊的概念,是成功呢,還是失敗呢,還是別的什麼含義呢?

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

Cache對於大多數互聯網項目而言,緩存的重要性,不言而喻!如果我們的應用系統,並不想使用一些第三方緩存組件(如redis),我們僅僅想在本地有一個功能足夠強大的緩存,很可惜JDK提供的那些SET/MAP還不行!

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

首先,這是一個本地緩存,guava提供的cache是一個簡潔、高效,易於維護的。為什麼這麼說呢?因為並沒有一個單獨的線程用於刷新 OR 清理cache,對於cache的操作,都是通過訪問/讀寫帶來的,也就是說在讀寫中完成緩存的刷新操作!其次,我們看到了,我們非常通俗的告訴cache,我們的緩存策略是什麼,SO EASY!在如此簡單的背後,是guava幫助我們做了很多事情,比如線程安全。讓異步回調更加簡單JDK中提供了Future/FutureTask/Callable來對異步回調進行支持,但是還是看上去挺複雜的,能不能更加簡單呢?比如註冊一個監聽回調。

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

我們可以通過guava對JDK提供的線程池進行裝飾,讓其具有異步回調監聽功能,然後在設置監聽器即可!到這裡,這篇文章也只介紹了guava的冰山一角,其實還有很多內容:比如反射、註解、網絡、併發、IO等等,好了,希望這篇文章讓你快速進階,快樂編程!你現在還想用阿里巴巴的編碼規範嗎?

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?

歡迎在留言區留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發,學習能力的提升上有新的認識,歡迎轉發分享給更多人。


猜你還想看


阿里、騰訊、百度、華為、京東最新面試題彙集

強軟弱虛引用,只有體會過了,才能記住!

Redis哨兵的配置和原理

答應我!別再寫上千行的類了!這樣的代碼讓我生不如死!

關注訂閱號「程序員小樂」,收看更多精彩內容
嘿,你在看嗎?

為什麼我不建議你用阿里巴巴Java規範?而是Google Guava 編程?



分享到:


相關文章: