<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>

          Guava,拯救垃圾代碼,效率提升N倍

          共 5935字,需瀏覽 12分鐘

           ·

          2021-11-19 11:23

          01、前世今生

          你好呀,我是 Guava。

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

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

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

          PS:star 這種事,只能求,不求沒效果??????。二哥開源的《Java 程序員進(jìn)階之路》專欄在 GitHub 上已經(jīng)收獲了 595 枚星標(biāo),鐵粉們趕緊去點點啦,幫二哥沖 600 star,筆芯

          https://github.com/itwanger/toBeBetterJavaer

          02、引入 Guava

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


          ????com.google.guava
          ????guava
          ????30.1-jre

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

          03、基本工具

          Doug Lea,java.util.concurrent 包的作者,曾說過一句話:“null 真糟糕”。Tony Hoare,圖靈獎得主、快速排序算法的作者,當(dāng)然也是 null 的創(chuàng)建者,也曾說過類似的話:“null 的使用,讓我損失了十億美元。”鑒于此,我用 Optional 來表示可能為 null 的對象。

          代碼示例如下所示。

          Optional?possible?=?Optional.of(5);
          possible.isPresent();?//?returns?true
          possible.get();?//?returns?5

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

          • 我的 Optional 是 abstract 的,意味著我可以有子類對象;我大哥的是 final 的,意味著沒有子類對象。

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

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

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

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

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

          04、集合

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

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

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

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

          與 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)的不是真正的不可變集合,當(dāng)原始集合被修改后,不可變集合里面的元素也是跟著發(fā)生變化。

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

          List?stringArrayList?=?Lists.newArrayList("雷軍","喬布斯");
          ImmutableList?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,可以多次添加相等的元素。當(dāng)把 Multiset 看成普通的 Collection 時,它表現(xiàn)得就像無序的 ArrayList;當(dāng)把 Multiset 看作 Map 時,它也提供了符合性能期望的查詢操作。

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

          • BiMap,一種特殊的 Map,可以用 inverse() 反轉(zhuǎn)BiMap 的鍵值映射;保證值是唯一的,因此 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,可以按照指定的分隔符把字符串序列進(jìn)行拆分。

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

          06、緩存

          緩存在很多場景下都是相當(dāng)有用的。你應(yīng)該知道,檢索一個值的代價很高,尤其是需要不止一次獲取值的時候,就應(yīng)當(dāng)考慮使用緩存。

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

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

          來個示例你感受下吧。

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

          ????CacheLoader?cacheLoader?=?new?CacheLoader()?{
          ????????//?如果找不到元素,會調(diào)用這里
          ????????@Override
          ????????public?Animal?load(String?s)?{
          ????????????return?null;
          ????????}
          ????};
          ????LoadingCache?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?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、尾聲

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

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



          這是《Java 程序員進(jìn)階之路》專欄的第 70 篇。該專欄風(fēng)趣幽默、通俗易懂,對 Java 愛好者極度友好和舒適??,內(nèi)容包括但不限于 Java 基礎(chǔ)、Java 集合框架、Java IO、Java 并發(fā)編程、Java 虛擬機(jī)、Java 企業(yè)級開發(fā)(SSM、Spring Boot)等核心知識點。

          點擊上方名片,發(fā)送消息「03」 就可以獲取最新版《Java 程序員進(jìn)階之路》PDF 版了,讓我們一起成為更好的 Java 工程師吧,沖!

          瀏覽 104
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  亚洲无码 国产精品 豆花 | 天天操天天摸天天碰 | 人人操狠狠撸 | 五月天性爱片 | 一卡二卡国产在线 |