国产精品亚洲一区-欧美日韩国产在线-伊人成人在线-国产精品无码久久久久-亚洲国产成人91精品-欧美成人精品欧美一级乱黄

二維碼
企資網(wǎng)

掃一掃關(guān)注

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

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

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

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

前言

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

  • LoadingCache(本地緩存)
  • Multimap 和 Multiset
  • BiMap
  • Table(表)
  • Sets和Maps(交并差)
  • EventBus(事件)
  • StopWatch(秒表)
  • Files(文件操作)
  • RateLimiter(限流器)
  • Guava Retry(重試)

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

    guava的maven配置引入

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

    LoadingCache

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

    CacheBuilder 方法參數(shù)

    描述

    initialCapacity(int initialCapacity)

    緩存池的初始大小

    concurrencyLevel(int concurrencyLevel)

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

    maximumSize(long maximumSize)

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

    weakValues()

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

    softValues()

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

    expireAfterWrite(long duration, TimeUnit unit)

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

    expireAfterAccess(long duration, TimeUnit unit)

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

    refreshAfterWrite(long duration, TimeUnit unit)

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

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

    監(jiān)聽器,緩存項被移除時會觸發(fā)

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

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

  • LoadingCache V get(K key), 獲取緩存值,如果鍵不存在值,將調(diào)用CacheLoader的load方法加載新值到該鍵中
  • 示例
    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

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

  • BiMap的鍵必須唯一,值也必須唯一,可以實(shí)現(xiàn)value和key互轉(zhuǎn)
  • 示例
    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

  • Table<R,C,V> table = HashbasedTable.create();,由泛型可以看出,table由雙主鍵R(行),C(列)共同決定,V是存儲值
  • 新增數(shù)據(jù):table.put(R,C,V)
  • 獲取數(shù)據(jù):V v = table.get(R,C)
  • 遍歷數(shù)據(jù): Set<R> set = table.rowKeySet(); Set<C> set = table.columnKeySet();   
  • 示例
    // 雙鍵的Map Map--> Table-->rowKey+columnKey+value  Table<String, String, Integer> tables = HashbasedTable.create();tables.put("csc", "lwl", 1);//row+column對應(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

  • EventBus是Guava的事件處理機(jī)制,是設(shè)計模式中的觀察者模式(生產(chǎn)/消費(fèi)者編程模型)的優(yōu)雅實(shí)現(xiàn)。對于事件監(jiān)聽和發(fā)布訂閱模式
  • EventBus內(nèi)部實(shí)現(xiàn)原理不復(fù)雜,EventBus內(nèi)部會維護(hù)一個Multimap<Class<?>, Subscriber> map,key就代表消息對應(yīng)的類(不同消息不同類,區(qū)分不同的消息)、value是一個Subscriber,Subscriber其實(shí)就是對應(yīng)消息處理者。如果有消息發(fā)布就去這個map里面找到這個消息對應(yīng)的Subscriber去執(zhí)行
  • 使用示例
    @Data@AllArgsConstructorpublic class OrderMessage {    String message;}//使用 @Subscribe 注解,表明使用dealWithEvent 方法處理 OrderMessage類型對應(yīng)的消息//可以注解多個方法,不同的方法 處理不同的對象消息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)行耗時:"+nanos);復(fù)制代碼

    Files文件操作

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

    方法

    描述

    Files.copy(File from, File to)

    復(fù)制文件

    Files.deleteDirectoryContents(File directory)

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

    Files.deleteRecursively(File file)

    刪除文件或者文件夾

    Files.move(File from, File to)

    移動文件

    Files.touch(File file)

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

    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ù)熱時間,從第一次acquire 或 tryAcquire 執(zhí)行開時計算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)復(fù)制代碼
  • 使用示例
    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ù)制代碼
  • 因?yàn)镽ateLimiter滯后處理的,所以第一次無論取多少都是零秒
  • 可以看到前四次的acquire,花了三秒時間去預(yù)熱數(shù)據(jù),在第五次到第八次的acquire耗時趨于平滑

    Guava Retry

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

    RetryerBuilder方法

    描述

    withRetryListener

    重試監(jiān)聽器

    withWaitStrategy

    失敗后重試間隔時間

    withStopStrategy

    停止策略

    withBlockStrategy

    阻塞策略BlockStrategy

    withAttemptTimeLimiter

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

    retryIfException

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

    retryIfRuntimeException

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

    retryIfExceptionOfType(Class<? extends Throwable> ex)

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

    retryIfException(Predicate<Throwable> exceptionPredicate)

    對異常判斷,是否重試

    retryIfResult(Predicate<V> resultPredicate)

    對返回結(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ù)制代碼
  • spring也有對應(yīng)的重試機(jī)制,相關(guān)文章可以看看重試框架Guava-Retry和spring-Retry


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

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

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

    粵ICP備16078936號

    微信

    關(guān)注
    微信

    微信二維碼

    WAP二維碼

    客服

    聯(lián)系
    客服

    聯(lián)系客服:

    在線QQ: 303377504

    客服電話: 020-82301567

    E_mail郵箱: weilaitui@qq.com

    微信公眾號: weishitui

    客服001 客服002 客服003

    工作時間:

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

    反饋

    用戶
    反饋

    主站蜘蛛池模板: 欧美一区二| 老司机成人免费精品视频 | 亚洲小视频在线播放 | 亚洲精品欧美精品一区二区 | 97se狠狠狠狠狠亚洲综合网 | 91成人免费在线视频 | 欧美精品束缚一区二区三区 | 97久久精品国产精品青草 | 久久中文字幕亚洲精品最新 | 综合久久精品 | 91久久香蕉国产线看观看软件 | 中文字幕在线观看一区二区三区 | 亚洲日本激情 | 波多野一区二区 | 国产精品色内内在线播放 | 久久久黄色片 | 欧美一级精品高清在线观看 | 操亚洲 | 97在线观看视频免费 | 国产亚洲欧美一区二区三区 | 国产成人精品视频频 | 一区二区精品在线 | 亚洲情a成黄在线观看动 | 一级毛片看一个 | 欧美日韩色黄大片在线视频 | 成人免费一级在线播放 | 日韩三级中文 | 国产日韩精品一区在线不卡 | 日韩免费一区二区三区在线 | 国产aⅴ精品一区二区三区久久 | 成人亲子乱子伦视频 | 久久99精品久久久久久综合 | 91国在线高清视频 | 久草视| 在线播放国产视频 | 美女又黄又免费的视频 | 99久久免费精品 | 韩国黄色一级毛片 | 国产在线精品一区免费香蕉 | 91精品国产高清久久久久久io | 久久久久欧美国产精品 |