二維碼
        企資網

        掃一掃關注

        當前位置: 首頁 » 企資快報 » 企業 » 正文

        工具篇_介紹幾個好用的guava工具類

        放大字體  縮小字體 發布日期:2021-09-13 13:46:09    作者:啊丟    瀏覽次數:19
        導讀

        前言平時我們都會封裝一些處理緩存或其他的小工具。但每個人都封裝一次,重復造輪子,有點費時間。有沒有一些好的工具庫推薦-guava。guava是谷歌基于java封裝好的開源庫,它的性能、實用性,比我們自己造的輪子更好

        前言

        平時我們都會封裝一些處理緩存或其他的小工具。但每個人都封裝一次,重復造輪子,有點費時間。有沒有一些好的工具庫推薦-guava。guava是谷歌基于java封裝好的開源庫,它的性能、實用性,比我們自己造的輪子更好,畢竟谷歌出品,下面介紹下幾個常用的guava工具類

      1. LoadingCache(本地緩存)
      2. Multimap 和 Multiset
      3. BiMap
      4. Table(表)
      5. Sets和Maps(交并差)
      6. EventBus(事件)
      7. StopWatch(秒表)
      8. Files(文件操作)
      9. RateLimiter(限流器)
      10. Guava Retry(重試)

        關注公眾號,一起交流,微信搜一搜: 潛行前行

        guava的maven配置引入

        <dependency>  <groupId>com.google.guava</groupId>  <artifactId>guava</artifactId>  <version>27.0-jre</version> </dependency>復制代碼

        LoadingCache

      11. LoadingCache 在實際場景中有著非常廣泛的使用,通常情況下如果遇到需要大量時間計算或者緩存值的場景,就應當將值保存到緩存中。LoadingCache 和 ConcurrentMap 類似,但又不盡相同。最大的不同是 ConcurrentMap 會永久的存儲所有的元素值直到他們被顯示的移除,但是 LoadingCache 會為了保持內存使用合理會根據配置自動將過期值移除
      12. 通常情況下,Guava caching 適用于以下場景:
      13. 花費一些內存來換取速度
      14. 一些 key 會被不止一次被調用
      15. 緩存內容有限,不會超過內存空間的值,Guava caches 不會存儲內容到文件或者到服務器外部,如果有此類需求考慮使用 Memcached, Redis
      16. LoadingCache 不能緩存 null key
      17. CacheBuilder 構造 LoadingCache 參數介紹

        CacheBuilder 方法參數

        描述

        initialCapacity(int initialCapacity)

        緩存池的初始大小

        concurrencyLevel(int concurrencyLevel)

        設置并發數

        maximumSize(long maximumSize)

        緩存池大小,在緩存項接近該大小時, Guava開始回收舊的緩存項

        weakValues()

        設置value的存儲引用是虛引用

        softValues()

        設置value的存儲引用是軟引用

        expireAfterWrite(long duration, TimeUnit unit)

        設置時間對象沒有被寫則對象從內存中刪除(在另外的線程里面不定期維護)

        expireAfterAccess(long duration, TimeUnit unit)

        設置時間對象沒有被讀/寫訪問則對象從內存中刪除(在另外的線程里面不定期維護)

        refreshAfterWrite(long duration, TimeUnit unit)

        和expireAfterWrite類似,不過不立馬移除key,而是在下次更新時刷新,這段時間可能會返回舊值

        removalListener( RemovalListener<? super K1, ? super V1> listener)

        監聽器,緩存項被移除時會觸發

        build(CacheLoader<? super K1, V1> loader)

        當數據不存在時,則使用loader加載數據

      18. LoadingCache V get(K key), 獲取緩存值,如果鍵不存在值,將調用CacheLoader的load方法加載新值到該鍵中
      19. 示例
        LoadingCache<Integer,Long> cacheMap = CacheBuilder.newBuilder().initialCapacity(10)    .concurrencyLevel(10)    .expireAfterAccess(Duration.ofSeconds(10))    .weakValues()    .recordStats()    .removalListener(new RemovalListener<Integer,Long>(){        @Override        public void onRemoval(RemovalNotification<Integer, Long> notification) {            System.out.println(notification.getValue());        }    })    .build(new CacheLoader<Integer,Long>(){        @Override        public Long load(Integer key) throws Exception {            return System.currentTimeMillis();        }    });cacheMap.get(1);復制代碼

        Multimap 和 MultiSet

      20. Multimap的特點其實就是可以包含有幾個重復Key的value,可以put進入多個不同value但是相同的key,但是又不會覆蓋前面的內容
      21. 示例
        //Multimap: key-value  key可以重復,value也可重復Multimap<String, String> multimap = ArrayListMultimap.create();multimap.put("csc","1");multimap.put("lwl","1");multimap.put("csc","1");multimap.put("lwl","one");System.out.println(multimap.get("csc"));System.out.println(multimap.get("lwl"));---------------------------[1, 1][1, one]復制代碼
      22. MultiSet 有一個相對有用的場景,就是跟蹤每種對象的數量,所以可以用來進行數量統計
      23. 示例
        //MultiSet: 無序+可重復   count()方法獲取單詞的次數  增強了可讀性+操作簡單Multiset<String> set = HashMultiset.create();set.add("csc");set.add("lwl");set.add("csc");System.out.println(set.size());System.out.println(set.count("csc"));---------------------------32復制代碼

        BiMap

      24. BiMap的鍵必須唯一,值也必須唯一,可以實現value和key互轉
      25. 示例
        BiMap<Integer,String> biMap = HashBiMap.create();biMap.put(1,"lwl");biMap.put(2,"csc");BiMap<String, Integer> map = biMap.inverse(); // value和key互轉map.forEach((v, k) -> System.out.println(v + "-" + k));復制代碼

        Table

      26. Table<R,C,V> table = HashbasedTable.create();,由泛型可以看出,table由雙主鍵R(行),C(列)共同決定,V是存儲值
      27. 新增數據:table.put(R,C,V)
      28. 獲取數據:V v = table.get(R,C)
      29. 遍歷數據: Set<R> set = table.rowKeySet(); Set<C> set = table.columnKeySet();   
      30. 示例
        // 雙鍵的Map Map--> Table-->rowKey+columnKey+value  Table<String, String, Integer> tables = HashbasedTable.create();tables.put("csc", "lwl", 1);//row+column對應的valueSystem.out.println(tables.get("csc","lwl"));復制代碼

        Sets和Maps

        // 不可變集合的創建ImmutableList<String> iList = ImmutableList.of("csc", "lwl");ImmutableSet<String> iSet = ImmutableSet.of("csc", "lwl");ImmutableMap<String, String> iMap = ImmutableMap.of("csc", "hello", "lwl", "world");復制代碼

        set的交集, 并集, 差集

        HashSet setA = newHashSet(1, 2, 3, 4, 5);  HashSet setB = newHashSet(4, 5, 6, 7, 8); //并集SetView union = Sets.union(setA, setB);   //差集 setA-setBSetView difference = Sets.difference(setA, setB);  //交集SetView intersection = Sets.intersection(setA, setB);  復制代碼

        map的交集,并集,差集

        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> mapDifference = Maps.difference(mapA, mapB);//mapA 和 mapB 相同的 entrySystem.out.println(mapDifference.entriesInCommon());//mapA 和 mapB key相同的value不同的 entrySystem.out.println(mapDifference.entriesDiffering());//只存在 mapA 的 entrySystem.out.println(mapDifference.entriesOnlyOnLeft());//只存在 mapB 的 entrySystem.out.println(mapDifference.entriesOnlyOnRight());;-------------結果-------------{c=3}{b=(2, 20)}{a=1}{d=4}復制代碼

        EventBus

      31. EventBus是Guava的事件處理機制,是設計模式中的觀察者模式(生產/消費者編程模型)的優雅實現。對于事件監聽和發布訂閱模式
      32. EventBus內部實現原理不復雜,EventBus內部會維護一個Multimap<Class<?>, Subscriber> map,key就代表消息對應的類(不同消息不同類,區分不同的消息)、value是一個Subscriber,Subscriber其實就是對應消息處理者。如果有消息發布就去這個map里面找到這個消息對應的Subscriber去執行
      33. 使用示例
        @Data@AllArgsConstructorpublic class OrderMessage {    String message;}//使用 @Subscribe 注解,表明使用dealWithEvent 方法處理 OrderMessage類型對應的消息//可以注解多個方法,不同的方法 處理不同的對象消息public class OrderEventListener {    @Subscribe    public void dealWithEvent(OrderMessage event) {        System.out.println("內容:" + event.getMessage());    }}-------------------------------------// new AsyncEventBus(String identifier, Executor executor);EventBus eventBus = new EventBus("lwl"); eventBus.register(new OrderEventListener());// 發布消息eventBus.post(new OrderMessage("csc"));復制代碼

        StopWatch

        Stopwatch stopwatch = Stopwatch.createStarted();for(int i=0; i<100000; i++){    // do some thing}long nanos = stopwatch.elapsed(TimeUnit.MILLISECONDS);System.out.println("邏輯代碼運行耗時:"+nanos);復制代碼

        Files文件操作

      34. 數據寫入
        File newFile = new File("D:/text.txt");Files.write("this is a test".getBytes(), newFile);//再次寫入會把之前的內容沖掉Files.write("csc".getBytes(), newFile);//追加寫Files.append("lwl", newFile, Charset.defaultCharset());復制代碼
      35. 文本數據讀取
        File newFile = new File("E:/text.txt");List<String> lines = Files.readLines(newFile, Charset.defaultCharset());復制代碼
      36. 其他操作

        方法

        描述

        Files.copy(File from, File to)

        復制文件

        Files.deleteDirectoryContents(File directory)

        刪除文件夾下的內容(包括文件與子文件夾)

        Files.deleteRecursively(File file)

        刪除文件或者文件夾

        Files.move(File from, File to)

        移動文件

        Files.touch(File file)

        創建或者更新文件的時間戳

        Files.getFileExtension(String file)

        獲得文件的擴展名

        Files.getNameWithoutExtension(String file)

        獲得不帶擴展名的文件名

        Files.map(File file, MapMode mode)

        獲取內存映射buffer

        RateLimiter

        //RateLimiter 構造方法,每秒限流permitsPerSecondpublic static RateLimiter create(double permitsPerSecond) //每秒限流 permitsPerSecond,warmupPeriod 則是數據初始預熱時間,從第一次acquire 或 tryAcquire 執行開時計算public static RateLimiter create(double permitsPerSecond, Duration warmupPeriod)//獲取一個令牌,阻塞,返回阻塞時間public double acquire()//獲取 permits 個令牌,阻塞,返回阻塞時間public double acquire(int permits)//獲取一個令牌,超時返回public boolean tryAcquire(Duration timeout)////獲取 permits 個令牌,超時返回public boolean tryAcquire(int permits, Duration timeout)復制代碼
      37. 使用示例
        RateLimiter limiter = RateLimiter.create(2, 3, TimeUnit.SECONDS);System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");System.out.println("get one permit cost time: " + limiter.acquire(1) + "s");---------------  結果 -------------------------get one permit cost time: 0.0sget one permit cost time: 1.331672sget one permit cost time: 0.998392sget one permit cost time: 0.666014sget one permit cost time: 0.498514sget one permit cost time: 0.498918sget one permit cost time: 0.499151sget one permit cost time: 0.488548s復制代碼
      38. 因為RateLimiter滯后處理的,所以第一次無論取多少都是零秒
      39. 可以看到前四次的acquire,花了三秒時間去預熱數據,在第五次到第八次的acquire耗時趨于平滑

        Guava Retry

      40. maven引入
        <dependency>  <groupId>com.github.rholder</groupId>  <artifactId>guava-retrying</artifactId>  <version>2.0.0</version></dependency>復制代碼
      41. RetryerBuilder 構造方法

        RetryerBuilder方法

        描述

        withRetryListener

        重試監聽器

        withWaitStrategy

        失敗后重試間隔時間

        withStopStrategy

        停止策略

        withBlockStrategy

        阻塞策略BlockStrategy

        withAttemptTimeLimiter

        執行時間限制策略

        retryIfException

        發生異常,則重試

        retryIfRuntimeException

        發生RuntimeException異常,則重試

        retryIfExceptionOfType(Class<? extends Throwable> ex)

        發生ex異常,則重試

        retryIfException(Predicate<Throwable> exceptionPredicate)

        對異常判斷,是否重試

        retryIfResult(Predicate<V> resultPredicate)

        對返回結果判斷,是否重試

        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()    .retryIfException()    .retryIfResult(Predicates.equalTo(false))    .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(1, TimeUnit.SECONDS))    .withStopStrategy(StopStrategies.stopAfterAttempt(5))    .build();//Retryer調用                retryer.call(() -> true);復制代碼
      42. spring也有對應的重試機制,相關文章可以看看重試框架Guava-Retry和spring-Retry


        作者:潛行前行
        鏈接:https://juejin.cn/post/6974202216768864264
        來源:掘金
        著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

      43.  
        (文/啊丟)
        免責聲明
        本文僅代表作發布者:啊丟個人觀點,本站未對其內容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內容,一經發現,立即刪除,需自行承擔相應責任。涉及到版權或其他問題,請及時聯系我們刪除處理郵件:weilaitui@qq.com。
         

        Copyright ? 2016 - 2025 - 企資網 48903.COM All Rights Reserved 粵公網安備 44030702000589號

        粵ICP備16078936號

        微信

        關注
        微信

        微信二維碼

        WAP二維碼

        客服

        聯系
        客服

        聯系客服:

        在線QQ: 303377504

        客服電話: 020-82301567

        E_mail郵箱: weilaitui@qq.com

        微信公眾號: weishitui

        客服001 客服002 客服003

        工作時間:

        周一至周五: 09:00 - 18:00

        反饋

        用戶
        反饋

        无码AV动漫精品一区二区免费| 亚洲AV综合色区无码另类小说| 日韩乱码人妻无码中文字幕 | 中文字幕一区二区精品区| 日韩丰满少妇无码内射| 亚洲天堂中文字幕| 极品粉嫩嫩模大尺度无码视频 | 亚洲成av人片在线观看无码不卡| 亚洲AV蜜桃永久无码精品| 亚洲AV无码一区二区二三区入口 | 中文字幕精品亚洲无线码一区| 性无码专区无码片| 特级做A爰片毛片免费看无码| 人妻无码αv中文字幕久久琪琪布| 免费人妻无码不卡中文字幕系| 十八禁视频在线观看免费无码无遮挡骂过 | 天堂亚洲国产中文在线| 久久久久久国产精品免费无码| 炫硕日本一区二区三区综合区在线中文字幕 | 天堂а√中文最新版地址在线| 国产亚洲?V无码?V男人的天堂| 亚洲AV无码不卡无码| 欧美精品丝袜久久久中文字幕| 美丽姑娘免费观看在线观看中文版 | 午夜无码A级毛片免费视频 | 国产成人A亚洲精V品无码| 中文字幕视频一区| 人妻中文字幕无码专区| 中文在线最新版天堂bt| 亚洲av中文无码| 伊人蕉久中文字幕无码专区| 蜜臀AV无码国产精品色午夜麻豆| 国产在线无码不卡影视影院 | 亚洲av激情无码专区在线播放| 日韩人妻无码一区二区三区 | 日本中文字幕在线2020| 天堂中文在线最新版| √天堂中文www官网| 久久99中文字幕久久| 久久精品天天中文字幕人妻| 精品人妻中文av一区二区三区 |