為什么強烈推薦 Java 程序員使用 Google Guava 編程敦锌!

備用標題:Google guava,牛逼的腳手架谬泌。

Guava - 拯救垃圾代碼滔韵,寫出優(yōu)雅高效,效率提升N倍

Guava掌实,一線大廠都在用開源工具類E泸摺!贱鼻!

Guava宴卖,真優(yōu)秀!

01邻悬、前世今生

你好呀症昏,我是 Guava。

1995 年的時候父丰,我的“公明”哥哥——Java 出生了肝谭。經(jīng)過 20 年的發(fā)展,他已經(jīng)成為世界上最流行的編程語言了蛾扇,請允許我有失公允的把“之一”給去了攘烛。

雖然他時常遭受著各種各樣的吐槽,但他始終沒有停下前進的腳步镀首。除了他本身的不斷進化坟漱,圍繞著他的大大小小的兄弟們也在不斷地更新迭代。我正是在這樣的背景下應運而生的更哄,我簡單易用芋齿,對我大哥是一個非常好的補充腥寇,可以說,只要你有使用我哥作為開發(fā)語言的項目沟突,幾乎都能看到我的身影花颗。

我由 Google 公司開源,目前在 GitHub 上已經(jīng)有 39.9k 的鐵粉了惠拭,由此可以證明我的受歡迎程度扩劝。

我的身體里主要包含有這些常用的模塊:集合 [collections] 、緩存 [caching] 职辅、原生類型支持 [primitives support] 棒呛、并發(fā)庫 [concurrency libraries] 、通用注解 [common annotations] 域携、字符串處理 [string processing] 簇秒、I/O 等。新版的 JDK 中已經(jīng)直接把我引入了秀鞭,可想而知我有多優(yōu)秀趋观,忍不住驕傲了。

這么說吧锋边,學好如何使用我皱坛,能讓你在編程中變得更快樂,寫出更優(yōu)雅的代碼豆巨!

02剩辟、引入 Guava

如果你要在 Maven 項目使用我的話,需要先在 pom.xml 文件中引入我的依賴往扔。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version>
</dependency>

一點要求贩猎,JDK 版本需要在 8 以上。

03萍膛、基本工具

Doug Lea吭服,java.util.concurrent 包的作者,曾說過一句話:“null 真糟糕”蝗罗。Tony Hoare噪馏,圖靈獎得主、快速排序算法的作者绿饵,當然也是 null 的創(chuàng)建者欠肾,也曾說過類似的話:“null 的使用,讓我損失了十億美元拟赊〈烫遥”鑒于此,我用 Optional 來表示可能為 null 的對象吸祟。

代碼示例如下所示瑟慈。

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

我大哥在 JDK 8 中新增了 Optional 類桃移,顯然是從我這借鑒過去的,不過他的和我的有些不同。

  • 我的 Optional 是 abstract 的,意味著我可以有子類對象焦除;我大哥的是 final 的母谎,意味著沒有子類對象监憎。

  • 我的 Optional 實現(xiàn)了 Serializable 接口,可以序列化;我大哥的沒有。

  • 我的一些方法和我大哥的也不盡相同绞惦。

使用 Optional 除了賦予 null 語義,增加了可讀性洋措,最大的優(yōu)點在于它是一種傻瓜式的防護济蝉。Optional 迫使你積極思考引用缺失的情況,因為你必須顯式地從 Optional 獲取引用菠发。

除了 Optional 之外王滤,我還提供了:

  • 參數(shù)校驗
  • 常見的 Object 方法,比如說 Objects.equals滓鸠、Objects.hashCode淑仆,JDK 7 引入的 Objects 類提供同樣的方法,當然也是從我這借鑒的靈感哥力。
  • 更強大的比較器

04、集合

首先我來說一下墩弯,為什么需要不可變集合吩跋。

  • 保證線程安全。在并發(fā)程序中渔工,使用不可變集合既保證線程的安全性锌钮,也大大地增強了并發(fā)時的效率(跟并發(fā)鎖方式相比)。

  • 如果一個對象不需要支持修改操作引矩,不可變的集合將會節(jié)省空間和時間的開銷梁丘。

  • 可以當作一個常量來對待,并且集合中的對象在以后也不會被改變旺韭。

與 JDK 中提供的不可變集合相比氛谜,我提供的 Immutable 才是真正的不可變,我為什么這么說呢区端?來看下面這個示例值漫。

下面的代碼利用 JDK 的 Collections.unmodifiableList(list) 得到一個不可修改的集合 unmodifiableList。

List list = new ArrayList();
list.add("雷軍");
list.add("喬布斯");

List unmodifiableList = Collections.unmodifiableList(list);
unmodifiableList.add("馬云");

運行代碼將會出現(xiàn)以下異常:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1060)
    at com.itwanger.guava.NullTest.main(NullTest.java:29)

很好织盼,執(zhí)行 unmodifiableList.add() 的時候拋出了 UnsupportedOperationException 異常杨何,說明 Collections.unmodifiableList() 返回了一個不可變集合酱塔。但真的是這樣嗎?

你可以把 unmodifiableList.add() 換成 list.add()危虱。

List list = new ArrayList();
list.add("雷軍");
list.add("喬布斯");

List unmodifiableList = Collections.unmodifiableList(list);
list.add("馬云");

再次執(zhí)行的話羊娃,程序并沒有報錯,并且你會發(fā)現(xiàn) unmodifiableList 中真的多了一個元素埃跷。說明什么呢蕊玷?

Collections.unmodifiableList(…) 實現(xiàn)的不是真正的不可變集合,當原始集合被修改后捌蚊,不可變集合里面的元素也是跟著發(fā)生變化集畅。

我就不會犯這種錯,來看下面的代碼缅糟。

List<String> stringArrayList = Lists.newArrayList("雷軍","喬布斯");
ImmutableList<String> immutableList = ImmutableList.copyOf(stringArrayList);
immutableList.add("馬云");

嘗試 immutableList.add() 的時候會拋出 UnsupportedOperationException挺智。我在源碼中已經(jīng)把 add() 方法廢棄了。

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final boolean add(E e) {
    throw new UnsupportedOperationException();
  }

嘗試 stringArrayList.add() 修改原集合的時候 immutableList 并不會因此而發(fā)生改變窗宦。

除了不可變集合以外赦颇,我還提供了新的集合類型,比如說:

  • Multiset赴涵,可以多次添加相等的元素媒怯。當把 Multiset 看成普通的 Collection 時,它表現(xiàn)得就像無序的 ArrayList髓窜;當把 Multiset 看作 Map<E, Integer> 時扇苞,它也提供了符合性能期望的查詢操作。

  • Multimap寄纵,可以很容易地把一個鍵映射到多個值鳖敷。

  • BiMap,一種特殊的 Map程拭,可以用 inverse() 反轉
    BiMap<K, V> 的鍵值映射定踱;保證值是唯一的,因此 values() 返回 Set 而不是普通的 Collection恃鞋。

05崖媚、字符串處理

字符串表示字符的不可變序列,創(chuàng)建后就不能更改恤浪。在我們?nèi)粘5墓ぷ髦谐┭疲址氖褂梅浅nl繁,熟練的對其操作可以極大的提升我們的工作效率水由。

我提供了連接器——Joiner敢课,可以用分隔符把字符串序列連接起來。下面的代碼將會返回“雷軍; 喬布斯”,你可以使用 useForNull(String) 方法用某個字符串來替換 null直秆,而不像 skipNulls() 方法那樣直接忽略 null濒募。

Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("雷軍", null, "喬布斯");

我還提供了拆分器—— Splitter,可以按照指定的分隔符把字符串序列進行拆分圾结。

Splitter.on(',')
        .trimResults()
        .omitEmptyStrings()
        .split("雷軍,喬布斯,,   沉默王二");

06瑰剃、緩存

緩存在很多場景下都是相當有用的。你應該知道筝野,檢索一個值的代價很高晌姚,尤其是需要不止一次獲取值的時候,就應當考慮使用緩存歇竟。

我提供的 Cache 和 ConcurrentMap 很相似挥唠,但也不完全一樣。最基本的區(qū)別是 ConcurrentMap 會一直保存所有添加的元素焕议,直到顯式地移除宝磨。相對地,我提供的 Cache 為了限制內(nèi)存占用盅安,通常都設定為自動回收元素唤锉。

如果你愿意消耗一些內(nèi)存空間來提升速度,你能預料到某些鍵會被查詢一次以上别瞭,緩存中存放的數(shù)據(jù)總量不會超出內(nèi)存容量窿祥,就可以使用 Cache。

來個示例你感受下吧蝙寨。

@Test
public void testCache() throws ExecutionException, InterruptedException {

    CacheLoader cacheLoader = new CacheLoader<String, Animal>() {
        // 如果找不到元素晒衩,會調(diào)用這里
        @Override
        public Animal load(String s) {
            return null;
        }
    };
    LoadingCache<String, Animal> loadingCache = CacheBuilder.newBuilder()
        .maximumSize(1000) // 容量
        .expireAfterWrite(3, TimeUnit.SECONDS) // 過期時間
        .removalListener(new MyRemovalListener()) // 失效監(jiān)聽器
        .build(cacheLoader); //
    loadingCache.put("狗", new Animal("旺財", 1));
    loadingCache.put("貓", new Animal("湯姆", 3));
    loadingCache.put("狼", new Animal("灰太狼", 4));

    loadingCache.invalidate("貓"); // 手動失效

    Animal animal = loadingCache.get("狼");
    System.out.println(animal);
    Thread.sleep(4 * 1000);
    // 狼已經(jīng)自動過去,獲取為 null 值報錯
    System.out.println(loadingCache.get("狼"));
}

/**
 * 緩存移除監(jiān)聽器
 */
class MyRemovalListener implements RemovalListener<String, Animal> {

    @Override
    public void onRemoval(RemovalNotification<String, Animal> notification) {
        String reason = String.format("key=%s,value=%s,reason=%s", notification.getKey(), notification.getValue(), notification.getCause());
        System.out.println(reason);
    }
}

class Animal {
    private String name;
    private Integer age;

    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

CacheLoader 中重寫了 load 方法墙歪,這個方法會在查詢緩存沒有命中時被調(diào)用听系,我這里直接返回了 null,其實這樣會在沒有命中時拋出 CacheLoader returned null for key 異常信息箱亿。

MyRemovalListener 作為緩存元素失效時的監(jiān)聽類,在有元素緩存失效時會自動調(diào)用 onRemoval 方法弃秆,這里需要注意的是這個方法是同步方法届惋,如果這里耗時較長,會阻塞直到處理完成菠赚。

LoadingCache 就是緩存的主要操作對象了脑豹,常用的就是其中的 put 和 get 方法了。

07衡查、尾聲

上面介紹了我認為最常用的功能瘩欺,作為 Google 公司開源的 Java 開發(fā)核心庫,個人覺得實用性還是很高的(不然呢?嘿嘿嘿)俱饿。引入到你的項目后不僅能快速的實現(xiàn)一些開發(fā)中常用的功能歌粥,而且還可以讓代碼更加的優(yōu)雅簡潔。

我覺得適用于每一個 Java 項目拍埠,至于其他的一些功能失驶,比如說散列、事件總線枣购、數(shù)學運算嬉探、反射,就等待你去發(fā)掘了棉圈。

另外涩堤,我為你準備了一份中文版的官方文檔(部分目錄見上圖),一共 190 頁分瘾,寫得非常詳細胎围,強烈建議你通過下面的方式下載一份放在桌面上!

鏈接:https://pan.baidu.com/s/1hrfaArC3UH6_ZNZEWCKzXA 密碼:684a

推薦閱讀:

自學java芹敌,學多久可以自己找到工作痊远?

看完谷歌學長的刷題筆記,我決定 2021 年手撕這101道 Leetcode 算法題

如果內(nèi)容對你有所幫助的話氏捞,請給我點個贊吧碧聪,筆芯~,你最美你最帥液茎,你 2021 年發(fā)大財逞姿。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捆等,隨后出現(xiàn)的幾起案子滞造,更是在濱河造成了極大的恐慌,老刑警劉巖栋烤,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谒养,死亡現(xiàn)場離奇詭異,居然都是意外死亡明郭,警方通過查閱死者的電腦和手機买窟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薯定,“玉大人始绍,你說我怎么就攤上這事』爸叮” “怎么了亏推?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵学赛,是天一觀的道長。 經(jīng)常有香客問我吞杭,道長盏浇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任篇亭,我火速辦了婚禮缠捌,結果婚禮上,老公的妹妹穿的比我還像新娘译蒂。我一直安慰自己曼月,他們只是感情好,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布柔昼。 她就那樣靜靜地躺著哑芹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捕透。 梳的紋絲不亂的頭發(fā)上聪姿,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音乙嘀,去河邊找鬼末购。 笑死,一個胖子當著我的面吹牛虎谢,可吹牛的內(nèi)容都是我干的盟榴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼婴噩,長吁一口氣:“原來是場噩夢啊……” “哼擎场!你這毒婦竟也來了?” 一聲冷哼從身側響起几莽,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤迅办,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后章蚣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體站欺,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年纤垂,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾策。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡洒忧,死狀恐怖蝴韭,靈堂內(nèi)的尸體忽然破棺而出够颠,到底是詐尸還是另有隱情熙侍,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蛉抓,受9級特大地震影響庆尘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巷送,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一驶忌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笑跛,春花似錦付魔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至陈哑,卻和暖如春妻坝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惊窖。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工刽宪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人界酒。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓圣拄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盾计。 傳聞我的和親對象是個殘疾皇子售担,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容