二維碼
        企資網

        掃一掃關注

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

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

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

        前言平時我們都會封裝一些處理緩存或其他的小工具。但每個人都封裝一次,重復造輪子,有點費時間。有沒有一些好的工具庫推薦-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私拍| 欧洲成人午夜精品无码区久久| 国99精品无码一区二区三区 | 极品粉嫩嫩模大尺度无码视频| 少妇无码?V无码专区在线观看| 中文精品久久久久人妻| 亚洲AV无码一区二区三区在线观看| 亚洲AV无码久久精品蜜桃| 午夜视频在线观看www中文| 久久亚洲国产成人精品无码区| 亚洲中文字幕久久精品无码APP| 无码专区久久综合久中文字幕| 精品无码av一区二区三区| 人妻丰满熟妇aⅴ无码| 天堂а√中文在线| 99在线精品国自产拍中文字幕| 人妻无码αv中文字幕久久琪琪布| 中文字幕永久一区二区三区在线观看| 中文字幕无码AV波多野吉衣| 精品无码三级在线观看视频| 日韩精品人妻系列无码专区免费 | 精品多人p群无码| 中文无码熟妇人妻AV在线| 中文精品久久久久国产网址| 中文字幕乱码中文乱码51精品| 久久亚洲精品无码播放| 18无码粉嫩小泬无套在线观看| 人妻丰满熟妞av无码区| 无码超乳爆乳中文字幕久久| 无套内射在线无码播放| 中文精品无码中文字幕无码专区 | 亚洲日韩乱码中文无码蜜桃臀网站 | 超清无码无卡中文字幕| 中文字幕亚洲一区二区va在线| 最近免费中文字幕大全高清大全1| 中文字字幕在线中文乱码不卡| 惠民福利中文字幕人妻无码乱精品| 黄桃AV无码免费一区二区三区| 无码人妻一区二区三区免费看 | 无码专区天天躁天天躁在线| 亚洲一区AV无码少妇电影☆|