<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 Google Guava 編程強(qiáng)過(guò)阿里巴巴規(guī)范?

          共 4682字,需瀏覽 10分鐘

           ·

          2021-07-05 10:11

          不點(diǎn)藍(lán)字,我們哪來(lái)故事?

          每天 11 點(diǎn)更新文章,餓了點(diǎn)外賣,點(diǎn)擊 ??《無(wú)門(mén)檻外賣優(yōu)惠券,每天免費(fèi)領(lǐng)!》

          來(lái)源:jianshu.com/p/97778b21bd00

          • 以面向?qū)ο笏枷胩幚碜址?Joiner/Splitter/CharMatcher
          • 對(duì)基本類型進(jìn)行支持
          • 對(duì)JDK集合的有效補(bǔ)充
          • 函數(shù)式編程:Functions
          • 斷言:Predicate
          • check null and other:Optional、Preconditions
          • Cache is king
          • 讓異步回調(diào)更加簡(jiǎn)單
          • Summary

          目前Google Guava在實(shí)際應(yīng)用中非常廣泛,本篇博客將以博主對(duì)Guava使用的認(rèn)識(shí)以及在項(xiàng)目中的經(jīng)驗(yàn)來(lái)給大家分享!正如標(biāo)題所言,學(xué)習(xí)使用Google Guava可以讓你快樂(lè)編程,寫(xiě)出優(yōu)雅的JAVA代碼!

          以面向?qū)ο笏枷胩幚碜址?Joiner/Splitter/CharMatcher

          JDK提供的String還不夠好么?

          也許還不夠友好,至少讓我們用起來(lái)還不夠爽,還得操心!

          舉個(gè)栗子,比如String提供的split方法,我們得關(guān)心空字符串吧,還得考慮返回的結(jié)果中存在null元素吧,只提供了前后trim的方法(如果我想對(duì)中間元素進(jìn)行trim呢)。

          那么,看下面的代碼示例,guava讓你不必在操心這些:

          Joiner/Splitter

          Joiner是連接器,Splitter是分割器,通常我們會(huì)把它們定義為static final,利用on生成對(duì)象后在應(yīng)用到String進(jìn)行處理,這是可以復(fù)用的。要知道apache commons StringUtils提供的都是static method。更加重要的是,guava提供的Joiner/Splitter是經(jīng)過(guò)充分測(cè)試,它的穩(wěn)定性和效率要比apache高出不少,這個(gè)你可以自行測(cè)試下~

          發(fā)現(xiàn)沒(méi)有我們想對(duì)String做什么操作,就是生成自己定制化的Joiner/Splitter,多么直白,簡(jiǎn)單,流暢的API!

          對(duì)于Joiner,常用的方法是  跳過(guò)NULL元素:skipNulls()  /  對(duì)于NULL元素使用其他替代:useForNull(String)

          對(duì)于Splitter,常用的方法是:trimResults()/omitEmptyStrings()。注意拆分的方式,有字符串,還有正則,還有固定長(zhǎng)度分割(太貼心了?。?/strong>

          其實(shí)除了Joiner/Splitter外,guava還提供了字符串匹配器:CharMatcher

          CharMatcher

          CharMatcher,將字符的匹配和處理解耦,并提供豐富的方法供你使用!

          對(duì)基本類型進(jìn)行支持

          guava對(duì)JDK提供的原生類型操作進(jìn)行了擴(kuò)展,使得功能更加強(qiáng)大!

          Ints

          guava提供了Bytes/Shorts/Ints/Iongs/Floats/Doubles/Chars/Booleans這些基本數(shù)據(jù)類型的擴(kuò)展支持,只有你想不到的,沒(méi)有它沒(méi)有的!

          對(duì)JDK集合的有效補(bǔ)充

          灰色地帶:Multiset

          JDK的集合,提供了有序且可以重復(fù)的List,無(wú)序且不可以重復(fù)的Set。那這里其實(shí)對(duì)于集合涉及到了2個(gè)概念,一個(gè)order,一個(gè)dups。那么List vs Set,and then some ?

          Multiset

          Multiset是什么,我想上面的圖,你應(yīng)該了解它的概念了。Multiset就是無(wú)序的,但是可以重復(fù)的集合,它就是游離在List/Set之間的“灰色地帶”!

          (至于有序的,不允許重復(fù)的集合嘛,guava還沒(méi)有提供,當(dāng)然在未來(lái)應(yīng)該會(huì)提供UniqueList,我猜的,哈哈)

          來(lái)看一個(gè)Multiset的示例:

          Multiset Code

          Multiset自帶一個(gè)有用的功能,就是可以跟蹤每個(gè)對(duì)象的數(shù)量。

          Immutable vs unmodifiable

          來(lái)我們先看一個(gè)unmodifiable的例子:

          unmodifiable

          你看到JDK提供的unmodifiable的缺陷了嗎?

          實(shí)際上,Collections.unmodifiableXxx所返回的集合和源集合是同一個(gè)對(duì)象,只不過(guò)可以對(duì)集合做出改變的API都被override,會(huì)拋出UnsupportedOperationException。

          也即是說(shuō)我們改變?cè)醇希瑢?dǎo)致不可變視圖(unmodifiable View)也會(huì)發(fā)生變化,oh my god!

          當(dāng)然,在不使用guava的情況下,我們是怎么避免上面的問(wèn)題的呢?

          defensive copies

          上面揭示了一個(gè)概念:Defensive Copies,保護(hù)性拷貝。

          OK,unmodifiable看上去沒(méi)有問(wèn)題呢,但是guava依然覺(jué)得可以改進(jìn),于是提出了Immutable的概念,來(lái)看:

          Immutable

          就一個(gè)copyOf,你不會(huì)忘記,如此cheap~

          用Google官方的說(shuō)法是:we're using just one class,just say exactly what we mean,很了不起嗎(不僅僅是個(gè)概念,Immutable在COPY階段還考慮了線程的并發(fā)性等,很智能的!),O(∩_∩)O哈哈~

          guava提供了很多Immutable集合,比如ImmutableList/ImmutableSet/ImmutableSortedSet/ImmutableMap/......

          看一個(gè)ImmutableMap的例子:

          ImmutableMap

          可不可以一對(duì)多:Multimap

          JDK提供給我們的Map是一個(gè)鍵,一個(gè)值,一對(duì)一的,那么在實(shí)際開(kāi)發(fā)中,顯然存在一個(gè)KEY多個(gè)VALUE的情況(比如一個(gè)分類下的書(shū)本),我們往往這樣表達(dá):Map<k,List>,好像有點(diǎn)臃腫!臃腫也就算了,更加不爽的事,我們還得判斷KEY是否存在來(lái)決定是否new 一個(gè)LIST出來(lái),有點(diǎn)麻煩!更加麻煩的事情還在后頭,比如遍歷,比如刪除,so hard......

          來(lái)看guava如何替你解決這個(gè)大麻煩的:

          Multimap

          友情提示下,guava所有的集合都有create方法,這樣的好處在于簡(jiǎn)單,而且我們不必在重復(fù)泛型信息了。

          get()/keys()/keySet()/values()/entries()/asMap()都是非常有用的返回view collection的方法。

          Multimap的實(shí)現(xiàn)類有:ArrayListMultimap/HashMultimap/LinkedHashMultimap/TreeMultimap/ImmutableMultimap/......

          可不可以雙向:BiMap

          JDK提供的MAP讓我們可以find value by key,那么能不能通過(guò)find key by value呢,能不能KEY和VALUE都是唯一的呢。這是一個(gè)雙向的概念,即forward+backward。

          在實(shí)際場(chǎng)景中有這樣的需求嗎?比如通過(guò)用戶ID找到mail,也需要通過(guò)mail找回用戶名。沒(méi)有g(shù)uava的時(shí)候,我們需要create forward map AND create backward map,and now just let guava do that for you.

          BiMap

          biMap / biMap.inverse() / biMap.inverse().inverse() 它們是什么關(guān)系呢?

          你可以稍微看一下BiMap的源碼實(shí)現(xiàn),實(shí)際上,當(dāng)你創(chuàng)建BiMap的時(shí)候,在內(nèi)部維護(hù)了2個(gè)map,一個(gè)forward map,一個(gè)backward map,并且設(shè)置了它們之間的關(guān)系。

          因此,biMap.inverse()  != biMap ;biMap.inverse().inverse() == biMap

          可不可以多個(gè)KEY:Table

          我們知道數(shù)據(jù)庫(kù)除了主鍵外,還提供了復(fù)合索引,而且實(shí)際中這樣的多級(jí)關(guān)系查找也是比較多的,當(dāng)然我們可以利用嵌套的Map來(lái)實(shí)現(xiàn):Map<k1,Map<k2,v2>>。為了讓我們的代碼看起來(lái)不那么丑陋,guava為我們提供了Table。

          Table

          Table涉及到3個(gè)概念:rowKey,columnKey,value,并提供了多種視圖以及操作方法讓你更加輕松的處理多個(gè)KEY的場(chǎng)景。

          函數(shù)式編程:Functions

          Functions

          上面的代碼是為了完成將List集合中的元素,先截取5個(gè)長(zhǎng)度,然后轉(zhuǎn)成大寫(xiě)。

          函數(shù)式編程的好處在于在集合遍歷操作中提供自定義Function的操作,比如transform轉(zhuǎn)換。我們?cè)僖膊恍枰槐楸榈谋闅v集合,顯著的簡(jiǎn)化了代碼!

          對(duì)集合的transform操作可以通過(guò)Function完成

          斷言:Predicate

          Predicate最常用的功能就是運(yùn)用在集合的過(guò)濾當(dāng)中!

          filter

          需要注意的是Lists并沒(méi)有提供filter方法,不過(guò)你可以使用Collections2.filter完成!

          check null and other:Optional、Preconditions

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

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

          Preconditions/Optional

          Cache is king

          對(duì)于大多數(shù)互聯(lián)網(wǎng)項(xiàng)目而言,緩存的重要性,不言而喻!

          如果我們的應(yīng)用系統(tǒng),并不想使用一些第三方緩存組件(如redis),我們僅僅想在本地有一個(gè)功能足夠強(qiáng)大的緩存,很可惜JDK提供的那些SET/MAP還不行!

          CacheLoader

          首先,這是一個(gè)本地緩存,guava提供的cache是一個(gè)簡(jiǎn)潔、高效,易于維護(hù)的。為什么這么說(shuō)呢?因?yàn)椴](méi)有一個(gè)單獨(dú)的線程用于刷新 OR 清理cache,對(duì)于cache的操作,都是通過(guò)訪問(wèn)/讀寫(xiě)帶來(lái)的,也就是說(shuō)在讀寫(xiě)中完成緩存的刷新操作!

          其次,我們看到了,我們非常通俗的告訴cache,我們的緩存策略是什么,SO EASY!在如此簡(jiǎn)單的背后,是guava幫助我們做了很多事情,比如線程安全。

          讓異步回調(diào)更加簡(jiǎn)單

          JDK中提供了Future/FutureTask/Callable來(lái)對(duì)異步回調(diào)進(jìn)行支持,但是還是看上去挺復(fù)雜的,能不能更加簡(jiǎn)單呢?比如注冊(cè)一個(gè)監(jiān)聽(tīng)回調(diào)。

          異步回調(diào)

          我們可以通過(guò)guava對(duì)JDK提供的線程池進(jìn)行裝飾,讓其具有異步回調(diào)監(jiān)聽(tīng)功能,然后在設(shè)置監(jiān)聽(tīng)器即可!

          Summary

          到這里,這篇文章也只介紹了guava的冰山一角,其實(shí)還有很多內(nèi)容:

          guava package

          比如反射、注解、網(wǎng)絡(luò)、并發(fā)、IO等等

          好了,希望這篇文章讓你快速進(jìn)階,快樂(lè)編程!

          - END -

          往期推薦

          為取消大小周而歡呼?字節(jié)員工可不那么想...

          Exception經(jīng)驗(yàn)之談,萬(wàn)萬(wàn)沒(méi)想到被很多團(tuán)隊(duì)采納!

          美團(tuán)面試:JVM 堆內(nèi)存溢出后,其他線程是否可繼續(xù)工作?

          圖解 Spring 循環(huán)依賴!

          下方二維碼關(guān)注我

          技術(shù)草根,堅(jiān)持分享 編程,算法,架構(gòu)

          看完文章,餓了點(diǎn)外賣,點(diǎn)擊 ??《無(wú)門(mén)檻外賣優(yōu)惠券,每天免費(fèi)領(lǐng)!》

          朋友,助攻一把!點(diǎn)個(gè)在看!
          瀏覽 87
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕一区二区三区四区五区人 | 丁香久久 | 亚洲天堂高清无码 | 色先锋AV | 人人爱人人揉 |