激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java的Guava工具包介紹

java的Guava工具包介紹

2021-09-08 11:01rickiyang Java教程

Java開發的同學應該都使用或者聽說過Google提供的Guava工具包。日常使用最多的肯定是集合相關的工具類,還有Guava cache,除了這些之外Guava還提供了很多有用的功能,鑒于日常想用的時候找不到,這里就梳理一下Guava中那些好用的工

集合

普通集合

?
1
2
3
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();

Set 取交集、并集、差集

?
1
2
3
4
5
6
7
8
HashSet<Integer> setA = Sets.newHashSet(1, 2, 3, 4, 5);
HashSet<Integer> setB = Sets.newHashSet(4, 5, 6, 7, 8);
Sets.SetView<Integer> union = Sets.union(setA, setB);
System.out.println("union:" + union);
Sets.SetView<Integer> difference = Sets.difference(setA, setB);
System.out.println("difference:" + difference);
Sets.SetView<Integer> intersection = Sets.intersection(setA, setB);
System.out.println("intersection:" + intersection);

map 取交集、并集、差集

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HashMap<String, Integer> mapA = Maps.newHashMap();
mapA.put("a", 1);
mapA.put("b", 2);
mapA.put("c", 3);
HashMap<String, Integer> mapB = Maps.newHashMap();
mapB.put("b", 20);
mapB.put("c", 3);
mapB.put("d", 4);
MapDifference<String, Integer> differenceMap = Maps.difference(mapA, mapB);
Map<String, MapDifference.ValueDifference<Integer>> entriesDiffering = differenceMap.entriesDiffering();
//左邊差集
Map<String, Integer> entriesOnlyLeft = differenceMap.entriesOnlyOnLeft();
//右邊差集
Map<String, Integer> entriesOnlyRight = differenceMap.entriesOnlyOnRight();
//交集
Map<String, Integer> entriesInCommon = differenceMap.entriesInCommon();
System.out.println(entriesDiffering);   // {b=(2, 20)}
System.out.println(entriesOnlyLeft);    // {a=1}
System.out.println(entriesOnlyRight);   // {d=4}
System.out.println(entriesInCommon);    // {c=3}

不可變集合(immutable)

不可變集合的特性有:

  • 在多線程操作下,是線程安全的;
  • 所有不可變集合會比可變集合更有效的利用資源;
  • 中途不可改變。

如果你的需求是想創建一個一經初始化后就不能再被改變的集合那么它適合你,因為這些工具類根本就沒給你提供修改的 API,這意味著你連犯錯誤的機會都沒有。

?
1
2
3
ImmutableList<Integer> iList = ImmutableList.of(12,54,87);
ImmutableSet<Integer> iSet = ImmutableSet.of(354,54,764,354);
ImmutableMap<String, Integer> iMap = ImmutableMap.of("k1", 453, "k2", 534);

以上 Immutable 開頭的相關集合類的 add、remove 方法都被聲明為 deprecated。當你手誤點到了這些方法發現是 deprecated 的時候你不會還想著使用吧。

注意:每個Guava immutable集合類的實現都拒絕 null 值。

有趣的集合

MultiSet: 無序+可重復

我們映像中的 Set 應該是無序的,元素不可重復的。MultiSet 顛覆了三觀,因為它可以重復。

定義一個 MultiSet 并添加元素:

?
1
2
3
4
5
6
Multiset<Integer> set = HashMultiset.create();
set.add(3);
set.add(3);
set.add(4);
set.add(5);
set.add(4);

你還可以添加指定個數的同一個元素:

?
1
set.add(7, 3);

這表示你想添加 3 個 7。

打印出來的 MultiSet 也很有意思:

?
1
[3 x 2, 4 x 2, 5, 7 x 3]

2個3,2個4,一個5,3個7。

獲取某個元素的個數:

?
1
int count = set.count(3);

這個工具類確實很有意思,幫我們實現了 word count。

Multimap :key 可以重復的 map

這個 map 也很有意思。正常的 map 為了區分不同的 key,它倒好,直接給你來一樣的 key 。

?
1
2
3
4
5
Multimap<String, String> map = LinkedHashMultimap.create();
map.put("key", "haha");
map.put("key", "haha1");
Collection<String> key = map.get("key");
System.out.println(key);

使用很簡單,用一個 key 可以獲取到該 key 對應的兩個值,結果用 list 返回。恕我無知,我還沒想到這個 map 能夠使用的場景。

java的Guava工具包介紹

Multimap 提供了多種實現:

 

Multimap 實現 key 字段類型 value 字段類型
ArrayListMultimap HashMap ArrayList
HashMultimap HashMap HashSet
LinkedListMultimap LinkedHashMap LinkedList
LinkedHashMultimap LinkedHashMap LinkedHashSet
TreeMultimap TreeMap TreeSet
ImmutableListMultimap ImmutableMap ImmutableList
ImmutableSetMultimap ImmutableMap ImmutableSet

 

雙向 Map

(Bidirectional Map) 鍵與值都不能重復

這個稍稍正常一點。如果 key 重復了則會覆蓋 key ,如果 value 重復了則會報錯。

?
1
2
3
4
5
6
7
8
public static void main(String[] args) {
  BiMap<String, String> biMap = HashBiMap.create();
  biMap.put("key", "haha");
  biMap.put("key", "haha1");
  biMap.put("key1", "haha");
  String value = biMap.get("key");
  System.out.println(value);
}

上面的示例中鍵 ”key“ 有兩個,運行可以發現 get 的時候會用 ”haha1" 覆蓋 ”haha“,另外 value 為 ”haha“ 也有兩個,你會發現運行上面的代碼不會報錯,這是因為 ”key“ 對應的 value 已經被 "haha1" 覆蓋了。否則是會報錯。

雙鍵 map - 超級實用

雙鍵的 map ,我突然感覺我發現了新大陸。比如我有一個業務場景是:根據職位和部門將公司人員區分開來。key 可以用職位 + 部門組成一個字符串,那我們有了雙鍵 map 之后就沒這種煩惱。

?
1
2
3
4
5
6
7
public static void main(String[] args) {
  Table<String, String, List<Object>> tables = HashBasedTable.create();
  tables.put("財務部", "總監", Lists.newArrayList());
  tables.put("財務部", "職員",Lists.newArrayList());
  tables.put("法務部", "助理",Lists.newArrayList());
  System.out.println(tables);
}

工具類

JDK里大家耳熟能詳的是Collections 這個集合工具類, 提供了一些基礎的集合處理轉換功能, 但是實際使用里很多需求并不是簡單的排序, 或者比較數值大小, 然后 Guava 在此基礎上做了許多的改進優化, 可以說是 Guava 最為成熟/流行的模塊之一。

  • 數組相關:Lists
  • 集合相關:Sets
  • map 相關:Maps

連接符(Joiner)和分隔符(Splitter)

Joiner 做為連接符的使用非常簡單,下例是將 list 轉為使用連接符連接的字符串:

?
1
2
3
4
5
6
7
8
List<Integer> list = Lists.newArrayList();
list.add(34);
list.add(64);
list.add(267);
list.add(865);
String result = Joiner.skipNulls().on("-").join(list);
System.out.println(result);
輸出:34-64-267-865

將 map 轉為自定義連接符連接的字符串:

?
1
2
3
4
5
6
7
Map<String, Integer> map = Maps.newHashMap();
map.put("key1", 45);
map.put("key2",234);
String result = Joiner.on(",").withKeyValueSeparator("=").join(map);
System.out.println(result);
輸出:
key1=45,key2=234

分隔符 Splitter 的使用也很簡單:

?
1
2
3
4
5
String str = "1-2-3-4-5-6";
List<String> list = Splitter.on("-").splitToList(str);
System.out.println(list);
輸出:
[1, 2, 3, 4, 5, 6]

如果字符串中帶有空格,還可以先去掉空格:

?
1
2
3
String str = "1-2-3-4-  5-  6   ";
List<String> list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(str);
System.out.println(list);

將 String 轉為 map:

?
1
2
3
4
5
String str = "key1=54,key2=28";
Map<String,String> map = Splitter.on(",").withKeyValueSeparator("=").split(str);
System.out.println(map);
輸出:
{key1=54, key2=28}

Comparator 的實現

Java 提供了 Comparator 可以用來對對象進行排序。Guava 提供了排序器 Ordering 類封裝了很多實用的操作。

Ordering 提供了一些有用的方法:

  • natural() 對可排序類型做自然排序,如數字按大小,日期按先后排序
  • usingToString() 按對象的字符串形式做字典排序[lexicographical ordering]
  • from(Comparator) 把給定的Comparator轉化為排序器
  • reverse() 獲取語義相反的排序器
  • nullsFirst() 使用當前排序器,但額外把null值排到最前面。
  • nullsLast() 使用當前排序器,但額外把null值排到最后面。
  • compound(Comparator) 合成另一個比較器,以處理當前排序器中的相等情況。 lexicographical() 基于處理類型T的排序器,返回該類型的可迭代對象Iterable的排序器。
  • onResultOf(Function) 對集合中元素調用Function,再按返回值用當前排序器排序。

示例:

?
1
2
3
4
UserInfo build = UserInfo.builder().uid(234L).gender(1).build();
UserInfo build1 = UserInfo.builder().uid(4354L).gender(0).build();
Ordering<UserInfo> byOrdering = Ordering.natural().nullsFirst().onResultOf((Function<UserInfo, Comparable<Integer>>) input -> input.getGender());
System.out.println(byOrdering.compare(build1, build));

build 的 gender 大于 build1 的,所以返回 -1,反之返回 1。

統計中間代碼運行時間

Stopwatch 類提供了時間統計的功能,相當于幫你封裝了調用 System.currentTimeMillis() 的邏輯。

?
1
2
3
4
5
6
7
8
9
Stopwatch stopwatch = Stopwatch.createStarted();
try {
  //TODO 模擬業務邏輯
  Thread.sleep(2000L);
} catch (InterruptedException e) {
  e.printStackTrace();
}
long nanos = stopwatch.elapsed(TimeUnit.SECONDS);
System.out.println(nanos);

Guava Cache - 本地緩存組件

Guava Cache 在日常的使用中非常地頻繁,甚至都沒有意識到這是第三方提供的工具類而是把它當成了 JDK 自帶的實現。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// LoadingCache是Cache的緩存實現
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
  //設置緩存大小
  .maximumSize(1000)
  //設置到期時間
  .expireAfterWrite(10, TimeUnit.MINUTES)
  //設置緩存里的值兩分鐘刷新一次
  .refreshAfterWrite(2, TimeUnit.MINUTES)
  //開啟緩存的統計功能
  .recordStats()
  //構建緩存
  .build(new CacheLoader<String, Object>() {
    //此處實現如果根據key找不到value需要去如何獲取
    @Override
    public Object load(String s) throws Exception {
      return new Object();
    }
    //如果批量加載有比反復調用load更優的方法則重寫這個方法
    @Override
    public Map<String, Object> loadAll(Iterable<? extends String> keys) throws Exception {
      return super.loadAll(keys);
    }
  });

設置本地緩存使用 CacheBuilder.newBuilder(),支持設置緩存大小,緩存過期時間,緩存刷新頻率等等。如果你想統計緩存的命中率, Guava Cache 也提供了這種能力幫你匯總當前緩存是否有效。

同時緩存如果因為某種原因未自動刷新或者清除,Guava Cache 也支持用戶手動調用 API 刷新或者清除緩存。

?
1
2
3
4
5
6
cache.invalidateAll();//清除所有緩存項
//清理的時機:在寫操作時順帶做少量的維護工作,或者偶爾在讀操作時做——如果寫操作實在太少的話
//如果想自己維護則可以調用Cache.cleanUp();
cache.cleanUp();
//另外有時候需要緩存中的數據做出變化重載一次,這個過程可以異步執行
cache.refresh("key");

單機限流工具類 - RateLimiter

常用的限流算法有 漏桶算法、令牌桶算法。這兩種算法各有側重點:

  • 漏桶算法:漏桶的意思就像一個漏斗一樣,水一滴一滴的滴下去,流出是勻速的。當訪問量過大的時候這個漏斗就會積水。漏桶算法的實現依賴隊列,一個處理器從隊頭依照固定頻率取出數據進行處理。如果請求量過大導致隊列堆滿那么新來的請求就會被拋棄。漏桶一般按照固定的速率流出。
  • 令牌桶則是存放固定容量的令牌,按照固定速率從桶中取出令牌。初始給桶中添加固定容量令牌,當桶中令牌不夠取出的時候則拒絕新的請求。令牌桶不限制取出令牌的速度,只要有令牌就能處理。所以令牌桶允許一定程度的突發,而漏桶主要目的是平滑流出。

RateLimiter 使用了令牌桶算法,提供兩種限流的實現方案:

  • 平滑突發限流(SmoothBursty)
  • 平滑預熱限流(SmoothWarmingUp)

實現平滑突發限流通過 RateLimiter 提供的靜態方法來創建:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
RateLimiter r = RateLimiter.create(5);
while (true) {
  System.out.println("get 1 tokens: " + r.acquire() + "s");
}
輸出:
get 1 tokens: 0.0s
get 1 tokens: 0.197059s
get 1 tokens: 0.195338s
get 1 tokens: 0.196918s
get 1 tokens: 0.19955s
get 1 tokens: 0.199062s
get 1 tokens: 0.195589s
get 1 tokens: 0.195061s
......

設置每秒放置的令牌數為 5 個,基本 0.2s 一次符合每秒 5 個的設置。保證每秒不超過 5 個達到了平滑輸出的效果。

在沒有請求使用令牌桶的時候,令牌會先創建好放在桶中,所以此時如果突然有突發流量進來,由于桶中有足夠的令牌可以快速響應。RateLimiter 在沒有足夠令牌發放時采用滯后處理的方式,前一個請求獲取令牌所需等待的時間由下一次請求來承受。

平滑預熱限流并不會像平滑突發限流一樣先將所有的令牌創建好,它啟動后會有一段預熱期,逐步將分發頻率提升到配置的速率。

比如下面例子創建一個平均分發令牌速率為 2,預熱期為 3 分鐘。由于設置了預熱時間是 3 秒,令牌桶一開始并不會 0.5 秒發一個令牌,而是形成一個平滑線性下降的坡度,頻率越來越高,在 3 秒鐘之內達到原本設置的頻率,以后就以固定的頻率輸出。這種功能適合系統剛啟動需要一點時間來“熱身”的場景。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS);
while (true) {
  System.out.println("get 1 tokens: " + r.acquire(1) + "s");
  System.out.println("get 1 tokens: " + r.acquire(1) + "s");
  System.out.println("end");
}
輸出:
get 1 tokens: 0.0s
get 1 tokens: 1.33068s
end
get 1 tokens: 0.995792s
get 1 tokens: 0.662838s
end
get 1 tokens: 0.494775s
get 1 tokens: 0.497293s
end
get 1 tokens: 0.49966s
get 1 tokens: 0.49625s
end

從上面的輸出看前面兩次獲取令牌都很耗時,往后就越來越趨于平穩。

今天給大家介紹的常用的 Guava 工具類就這些,不過 JDK8 開始 Java官方 API 也在完善,比如像字符串相關的功能 JDK也很強大。都是工具,哪個好用就用哪個。

到此這篇關于java的Guava工具包介紹的文章就到這了,更多相關Guava工具包內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章,希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/rickiyang/p/14661374.html

延伸 · 閱讀

精彩推薦
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
主站蜘蛛池模板: 超碰一区 | 国产精品久久久久久久亚洲按摩 | 欧美成人免费tv在线播放 | 黄在线 | 国产激情精品一区二区三区 | 91综合影院| 麻豆国产一区 | 欧美一级鲁丝片免费看 | 国产亚洲欧美日韩高清 | 久操伊人 | 男女做性免费网站 | 久久经典| 欧洲成人一区 | 国产精品6区 | av电影在线观看网址 | 国产不卡av在线 | 一级一片免费看 | 亚洲欧美日韩精品久久 | 国产精品免费小视频 | 小雪奶水翁胀公吸小说最新章节 | 性少妇videosexfreexxx片 | 欧美性生活区 | 国产成年人小视频 | 国产一级aa大片毛片 | 成人网视频| 国产成人小视频在线观看 | 欧美一区二区网站 | 国产精品免费一区二区三区四区 | 一级空姐毛片 | 欧洲精品久久久久69精品 | 黄wwww | 免费观看一区二区三区视频 | 亚洲成人福利在线观看 | 欧美精品日日鲁夜夜添 | 草b视频在线观看 | 欧美一级三级在线观看 | 国产成人精品网站 | 欧美黄色看 | 国内免费视频成人精品 | 免费看成年人网站 | 国产亚洲区 |