自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Google Guava,優(yōu)秀的腳手架

開發(fā) 開發(fā)工具
1995 年的時(shí)候,我的“公明”哥哥——Java 出生了。經(jīng)過(guò) 20 年的發(fā)展,他已經(jīng)成為世界上最流行的編程語(yǔ)言了,請(qǐng)?jiān)试S我有失公允的把“之一”給去了。

 [[374241]]

本文轉(zhuǎn)載自微信公眾號(hào)「沉默王二」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系沉默王二公眾號(hào)。

01、前世今生

你好呀,我是 Guava。

1995 年的時(shí)候,我的“公明”哥哥——Java 出生了。經(jīng)過(guò) 20 年的發(fā)展,他已經(jīng)成為世界上最流行的編程語(yǔ)言了,請(qǐng)?jiān)试S我有失公允的把“之一”給去了。

雖然他時(shí)常遭受著各種各樣的吐槽,但他始終沒有停下前進(jìn)的腳步。除了他本身的不斷進(jìn)化,圍繞著他的大大小小的兄弟們也在不斷地更新迭代。我正是在這樣的背景下應(yīng)運(yùn)而生的,我簡(jiǎn)單易用,對(duì)我大哥是一個(gè)非常好的補(bǔ)充,可以說(shuō),只要你有使用我哥作為開發(fā)語(yǔ)言的項(xiàng)目,幾乎都能看到我的身影。

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

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

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

02、引入 Guava

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

  1. <dependency> 
  2.     <groupId>com.google.guava</groupId> 
  3.     <artifactId>guava</artifactId> 
  4.     <version>30.1-jre</version> 
  5. </dependency> 

一點(diǎn)要求,JDK 版本需要在 8 以上。

03、基本工具

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

代碼示例如下所示。

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

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

  • 我的 Optional 是 abstract 的,意味著我可以有子類對(duì)象;我大哥的是 final 的,意味著沒有子類對(duì)象。
  • 我的 Optional 實(shí)現(xiàn)了 Serializable 接口,可以序列化;我大哥的沒有。
  • 我的一些方法和我大哥的也不盡相同。

使用 Optional 除了賦予 null 語(yǔ)義,增加了可讀性,最大的優(yōu)點(diǎn)在于它是一種傻瓜式的防護(hù)。Optional 迫使你積極思考引用缺失的情況,因?yàn)槟惚仨氾@式地從 Optional 獲取引用。

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

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

04、集合

首先我來(lái)說(shuō)一下,為什么需要不可變集合。

  • 保證線程安全。在并發(fā)程序中,使用不可變集合既保證線程的安全性,也大大地增強(qiáng)了并發(fā)時(shí)的效率(跟并發(fā)鎖方式相比)。
  • 如果一個(gè)對(duì)象不需要支持修改操作,不可變的集合將會(huì)節(jié)省空間和時(shí)間的開銷。
  • 可以當(dāng)作一個(gè)常量來(lái)對(duì)待,并且集合中的對(duì)象在以后也不會(huì)被改變。

與 JDK 中提供的不可變集合相比,我提供的 Immutable 才是真正的不可變,我為什么這么說(shuō)呢?來(lái)看下面這個(gè)示例。

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

  1. List list = new ArrayList(); 
  2. list.add("雷軍"); 
  3. list.add("喬布斯"); 
  4.  
  5. List unmodifiableList = Collections.unmodifiableList(list); 
  6. unmodifiableList.add("馬云"); 

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

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

很好,執(zhí)行 unmodifiableList.add() 的時(shí)候拋出了 UnsupportedOperationException 異常,說(shuō)明 Collections.unmodifiableList() 返回了一個(gè)不可變集合。但真的是這樣嗎?

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

  1. List list = new ArrayList(); 
  2. list.add("雷軍"); 
  3. list.add("喬布斯"); 
  4.  
  5. List unmodifiableList = Collections.unmodifiableList(list); 
  6. list.add("馬云"); 

再次執(zhí)行的話,程序并沒有報(bào)錯(cuò),并且你會(huì)發(fā)現(xiàn) unmodifiableList 中真的多了一個(gè)元素。說(shuō)明什么呢?

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

我就不會(huì)犯這種錯(cuò),來(lái)看下面的代碼。

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

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

  1. /** 
  2.  * Guaranteed to throw an exception and leave the collection unmodified. 
  3.  * 
  4.  * @throws UnsupportedOperationException always 
  5.  * @deprecated Unsupported operation. 
  6.  */ 
  7. @CanIgnoreReturnValue 
  8. @Deprecated 
  9. @Override 
  10. public final boolean add(E e) { 
  11.   throw new UnsupportedOperationException(); 

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

除了不可變集合以外,我還提供了新的集合類型,比如說(shuō):

  • Multiset,可以多次添加相等的元素。當(dāng)把 Multiset 看成普通的 Collection 時(shí),它表現(xiàn)得就像無(wú)序的 ArrayList;當(dāng)把 Multiset 看作 Map
  • Multimap,可以很容易地把一個(gè)鍵映射到多個(gè)值。
  • BiMap,一種特殊的 Map,可以用 inverse() 反轉(zhuǎn)BiMap

05、字符串處理

字符串表示字符的不可變序列,創(chuàng)建后就不能更改。在我們?nèi)粘5墓ぷ髦?,字符串的使用非常頻繁,熟練的對(duì)其操作可以極大的提升我們的工作效率。

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

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

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

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

06、緩存

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

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

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

來(lái)個(gè)示例你感受下吧。

  1. @Test 
  2. public void testCache() throws ExecutionException, InterruptedException { 
  3.  
  4.     CacheLoader cacheLoader = new CacheLoader<String, Animal>() { 
  5.         // 如果找不到元素,會(huì)調(diào)用這里 
  6.         @Override 
  7.         public Animal load(String s) { 
  8.             return null
  9.         } 
  10.     }; 
  11.     LoadingCache<String, Animal> loadingCache = CacheBuilder.newBuilder() 
  12.         .maximumSize(1000) // 容量 
  13.         .expireAfterWrite(3, TimeUnit.SECONDS) // 過(guò)期時(shí)間 
  14.         .removalListener(new MyRemovalListener()) // 失效監(jiān)聽器 
  15.         .build(cacheLoader); // 
  16.     loadingCache.put("狗", new Animal("旺財(cái)", 1)); 
  17.     loadingCache.put("貓", new Animal("湯姆", 3)); 
  18.     loadingCache.put("狼", new Animal("灰太狼", 4)); 
  19.  
  20.     loadingCache.invalidate("貓"); // 手動(dòng)失效 
  21.  
  22.     Animal animal = loadingCache.get("狼"); 
  23.     System.out.println(animal); 
  24.     Thread.sleep(4 * 1000); 
  25.     // 狼已經(jīng)自動(dòng)過(guò)去,獲取為 null 值報(bào)錯(cuò) 
  26.     System.out.println(loadingCache.get("狼")); 
  27.  
  28. /** 
  29.  * 緩存移除監(jiān)聽器 
  30.  */ 
  31. class MyRemovalListener implements RemovalListener<String, Animal> { 
  32.  
  33.     @Override 
  34.     public void onRemoval(RemovalNotification<String, Animal> notification) { 
  35.         String reason = String.format("key=%s,value=%s,reason=%s", notification.getKey(), notification.getValue(), notification.getCause()); 
  36.         System.out.println(reason); 
  37.     } 
  38.  
  39. class Animal { 
  40.     private String name
  41.     private Integer age; 
  42.  
  43.     public Animal(String nameInteger age) { 
  44.         this.name = name
  45.         this.age = age; 
  46.     } 

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

MyRemovalListener 作為緩存元素失效時(shí)的監(jiān)聽類,在有元素緩存失效時(shí)會(huì)自動(dòng)調(diào)用 onRemoval 方法,這里需要注意的是這個(gè)方法是同步方法,如果這里耗時(shí)較長(zhǎng),會(huì)阻塞直到處理完成。

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

07、尾聲

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

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

 

責(zé)任編輯:武曉燕 來(lái)源: 沉默王二
相關(guān)推薦

2021-12-23 10:35:32

SpringCloud腳手架架構(gòu)

2016-09-07 15:35:06

VueReact腳手架

2021-05-21 05:22:52

腳手架工具項(xiàng)目

2020-03-20 08:32:41

物聯(lián)網(wǎng)腳手架傳感器

2018-08-30 16:08:37

Node.js腳手架工具

2018-06-11 14:39:57

前端腳手架工具node.js

2019-12-25 15:20:48

前端腳手架命令

2022-04-24 11:33:47

代碼管理工程

2023-11-21 17:36:04

OpenFeignSentinel

2014-08-15 09:36:06

2024-03-11 13:18:00

RustClap項(xiàng)目

2020-06-29 11:35:02

Spring BootJava腳手架

2022-01-14 14:09:11

腳手架代碼自定義

2017-07-21 09:56:46

Webpack3 Vue.js腳手架

2022-07-18 07:58:46

Spring工具工具類

2020-08-19 08:55:47

Redis緩存數(shù)據(jù)庫(kù)

2022-12-12 08:56:45

Vite3Vite

2021-11-08 09:35:09

Vue代碼前端

2009-09-16 15:05:58

CakePHP腳手架

2021-09-22 08:26:31

前端腳手架開源項(xiàng)目
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)