<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,牛逼的腳手架

          共 8130字,需瀏覽 17分鐘

           ·

          2021-03-06 04:18

          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 的使用,讓我損失了十億美元?!辫b于此,我用 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)建后就不能更改。在我們日常的工作中,字符串的使用非常頻繁,熟練的對其操作可以極大的提升我們的工作效率。

          我提供了連接器——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 為了限制內存占用,通常都設定為自動回收元素。

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

          來個示例你感受下吧。

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

              CacheLoader cacheLoader = new CacheLoader<String, Animal>() {
                  // 如果找不到元素,會調用這里
                  @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<StringAnimal{

              @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 方法,這個方法會在查詢緩存沒有命中時被調用,我這里直接返回了 null,其實這樣會在沒有命中時拋出 CacheLoader returned null for key 異常信息。

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

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

          07、尾聲

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


          往期推薦

          Google 開源的依賴注入庫,比 Spring 更小更快!


          我去,這幾個Linux指令太裝B了|動圖展示


          Spring 事務失效的 8 大場景,面試官直呼666...


          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  欧美成人在线无码 | 黄片免费观看 | 免费黄色免费片 | 亚洲图色在线 | 国内毛片毛片毛片毛片毛片毛片毛片 |