二維碼
        企資網(wǎng)

        掃一掃關(guān)注

        當(dāng)前位置: 首頁(yè) » 企資快報(bào) » 企業(yè) » 正文

        工具篇_介紹幾個(gè)好用的guava工具類

        放大字體  縮小字體 發(fā)布日期:2021-09-13 13:46:09    作者:啊丟    瀏覽次數(shù):10
        導(dǎo)讀

        前言平時(shí)我們都會(huì)封裝一些處理緩存或其他的小工具。但每個(gè)人都封裝一次,重復(fù)造輪子,有點(diǎn)費(fèi)時(shí)間。有沒(méi)有一些好的工具庫(kù)推薦-guava。guava是谷歌基于java封裝好的開源庫(kù),它的性能、實(shí)用性,比我們自己造的輪子更好

        前言

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

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

        關(guān)注公眾號(hào),一起交流,微信搜一搜: 潛行前行

        guava的maven配置引入

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

        LoadingCache

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

        CacheBuilder 方法參數(shù)

        描述

        initialCapacity(int initialCapacity)

        緩存池的初始大小

        concurrencyLevel(int concurrencyLevel)

        設(shè)置并發(fā)數(shù)

        maximumSize(long maximumSize)

        緩存池大小,在緩存項(xiàng)接近該大小時(shí), Guava開始回收舊的緩存項(xiàng)

        weakValues()

        設(shè)置value的存儲(chǔ)引用是虛引用

        softValues()

        設(shè)置value的存儲(chǔ)引用是軟引用

        expireAfterWrite(long duration, TimeUnit unit)

        設(shè)置時(shí)間對(duì)象沒(méi)有被寫則對(duì)象從內(nèi)存中刪除(在另外的線程里面不定期維護(hù))

        expireAfterAccess(long duration, TimeUnit unit)

        設(shè)置時(shí)間對(duì)象沒(méi)有被讀/寫訪問(wèn)則對(duì)象從內(nèi)存中刪除(在另外的線程里面不定期維護(hù))

        refreshAfterWrite(long duration, TimeUnit unit)

        和expireAfterWrite類似,不過(guò)不立馬移除key,而是在下次更新時(shí)刷新,這段時(shí)間可能會(huì)返回舊值

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

        監(jiān)聽器,緩存項(xiàng)被移除時(shí)會(huì)觸發(fā)

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

        當(dāng)數(shù)據(jù)不存在時(shí),則使用loader加載數(shù)據(jù)

      18. LoadingCache V get(K key), 獲取緩存值,如果鍵不存在值,將調(diào)用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);復(fù)制代碼

        Multimap 和 MultiSet

      20. Multimap的特點(diǎn)其實(shí)就是可以包含有幾個(gè)重復(fù)Key的value,可以put進(jìn)入多個(gè)不同value但是相同的key,但是又不會(huì)覆蓋前面的內(nèi)容
      21. 示例
        //Multimap: key-value  key可以重復(fù),value也可重復(fù)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]復(fù)制代碼
      22. MultiSet 有一個(gè)相對(duì)有用的場(chǎng)景,就是跟蹤每種對(duì)象的數(shù)量,所以可以用來(lái)進(jìn)行數(shù)量統(tǒng)計(jì)
      23. 示例
        //MultiSet: 無(wú)序+可重復(fù)   count()方法獲取單詞的次數(shù)  增強(qiáng)了可讀性+操作簡(jiǎn)單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復(fù)制代碼

        BiMap

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

        Table

      26. Table<R,C,V> table = HashbasedTable.create();,由泛型可以看出,table由雙主鍵R(行),C(列)共同決定,V是存儲(chǔ)值
      27. 新增數(shù)據(jù):table.put(R,C,V)
      28. 獲取數(shù)據(jù):V v = table.get(R,C)
      29. 遍歷數(shù)據(jù): 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對(duì)應(yīng)的valueSystem.out.println(tables.get("csc","lwl"));復(fù)制代碼

        Sets和Maps

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

        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);  復(fù)制代碼

        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());;-------------結(jié)果-------------{c=3}{b=(2, 20)}{a=1}{d=4}復(fù)制代碼

        EventBus

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

        StopWatch

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

        Files文件操作

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

        方法

        描述

        Files.copy(File from, File to)

        復(fù)制文件

        Files.deleteDirectoryContents(File directory)

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

        Files.deleteRecursively(File file)

        刪除文件或者文件夾

        Files.move(File from, File to)

        移動(dòng)文件

        Files.touch(File file)

        創(chuàng)建或者更新文件的時(shí)間戳

        Files.getFileExtension(String file)

        獲得文件的擴(kuò)展名

        Files.getNameWithoutExtension(String file)

        獲得不帶擴(kuò)展名的文件名

        Files.map(File file, MapMode mode)

        獲取內(nèi)存映射buffer

        RateLimiter

        //RateLimiter 構(gòu)造方法,每秒限流permitsPerSecondpublic static RateLimiter create(double permitsPerSecond) //每秒限流 permitsPerSecond,warmupPeriod 則是數(shù)據(jù)初始預(yù)熱時(shí)間,從第一次acquire 或 tryAcquire 執(zhí)行開時(shí)計(jì)算public static RateLimiter create(double permitsPerSecond, Duration warmupPeriod)//獲取一個(gè)令牌,阻塞,返回阻塞時(shí)間public double acquire()//獲取 permits 個(gè)令牌,阻塞,返回阻塞時(shí)間public double acquire(int permits)//獲取一個(gè)令牌,超時(shí)返回public boolean tryAcquire(Duration timeout)////獲取 permits 個(gè)令牌,超時(shí)返回public boolean tryAcquire(int permits, Duration timeout)復(fù)制代碼
      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");---------------  結(jié)果 -------------------------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復(fù)制代碼
      38. 因?yàn)镽ateLimiter滯后處理的,所以第一次無(wú)論取多少都是零秒
      39. 可以看到前四次的acquire,花了三秒時(shí)間去預(yù)熱數(shù)據(jù),在第五次到第八次的acquire耗時(shí)趨于平滑

        Guava Retry

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

        RetryerBuilder方法

        描述

        withRetryListener

        重試監(jiān)聽器

        withWaitStrategy

        失敗后重試間隔時(shí)間

        withStopStrategy

        停止策略

        withBlockStrategy

        阻塞策略BlockStrategy

        withAttemptTimeLimiter

        執(zhí)行時(shí)間限制策略

        retryIfException

        發(fā)生異常,則重試

        retryIfRuntimeException

        發(fā)生RuntimeException異常,則重試

        retryIfExceptionOfType(Class<? extends Throwable> ex)

        發(fā)生ex異常,則重試

        retryIfException(Predicate<Throwable> exceptionPredicate)

        對(duì)異常判斷,是否重試

        retryIfResult(Predicate<V> resultPredicate)

        對(duì)返回結(jié)果判斷,是否重試

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


        作者:潛行前行
        鏈接:https://juejin.cn/post/6974202216768864264
        來(lái)源:掘金
        著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

      43.  
        (文/啊丟)
        免責(zé)聲明
        本文僅代表作發(fā)布者:啊丟個(gè)人觀點(diǎn),本站未對(duì)其內(nèi)容進(jìn)行核實(shí),請(qǐng)讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問(wèn)題,請(qǐng)及時(shí)聯(lián)系我們刪除處理郵件:weilaitui@qq.com。
         

        Copyright ? 2016 - 2025 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號(hào)

        粵ICP備16078936號(hào)

        微信

        關(guān)注
        微信

        微信二維碼

        WAP二維碼

        客服

        聯(lián)系
        客服

        聯(lián)系客服:

        在線QQ: 303377504

        客服電話: 020-82301567

        E_mail郵箱: weilaitui@qq.com

        微信公眾號(hào): weishitui

        客服001 客服002 客服003

        工作時(shí)間:

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

        反饋

        用戶
        反饋

        成年无码av片在线| 午夜福利av无码一区二区| 国产亚洲精久久久久久无码77777| 无码一区二区三区| 一本一道av中文字幕无码 | 国产亚洲精品a在线无码| 亚洲欧美综合在线中文| 超清无码熟妇人妻AV在线电影| 国产成人亚洲综合无码精品| 日本中文字幕在线2020| 无码专区久久综合久中文字幕 | 曰韩人妻无码一区二区三区综合部| 成人毛片无码一区二区三区| 曰韩中文字幕在线中文字幕三级有码| 无码精品A∨在线观看| 波多野结衣在线aⅴ中文字幕不卡 波多野结衣在线中文 | 欧美日本道中文高清| 亚洲AV无码成人精品区蜜桃| 狠狠躁天天躁中文字幕无码| 亚洲AV综合色区无码一区| 久热中文字幕无码视频 | 久久精品aⅴ无码中文字字幕不卡| 亚洲一区精品无码| 久久精品aⅴ无码中文字字幕不卡| 精品无码一区二区三区爱欲九九| 最近中文字幕完整在线看一| 亚洲精品一级无码中文字幕| 亚洲AV无码乱码国产麻豆穿越 | 亚洲中文字幕无码久久2017| 乱色精品无码一区二区国产盗 | 免费VA在线观看无码| 无套中出丰满人妻无码| 人妻无码中文字幕免费视频蜜桃| 亚洲AⅤ永久无码精品AA| 亚洲AV无码专区亚洲AV伊甸园| 最近更新中文字幕第一页| 日韩AV无码不卡网站 | 午夜人性色福利无码视频在线观看| 最近中文字幕高清免费中文字幕mv| 久久亚洲AV无码西西人体| 无码av免费网站|