java實(shí)現(xiàn)固定大小隊(duì)列的幾種方式

最近團(tuán)隊(duì)有同學(xué)在開發(fā)中血柳,遇到一個需求载庭,統(tǒng)計(jì)最近10次的異常次數(shù)辙纬,咨詢有沒有類似的list豁遭。針對這個問題,記錄一下幾種處理方式贺拣。

基于Hutool中的FixedLinkedHashMap

引入maven依賴
<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-all</artifactId>
   <version>5.4.0</version>
</dependency>
使用示例
// 初始化時指定大小
private final FixedLinkedHashMap<String, Integer> fixedLinkedHashMap = new FixedLinkedHashMap<>(LIST_SIZE);

// 其余寫入和讀取操作同LinkedHashMap類似
// 對于key蓖谢,可以按照自己的業(yè)務(wù)需求填寫
fixedLinkedHashMap.put(UUID.randomUUID().toString(), 1);

// 讀取操作
// 獲取元素個數(shù)
long size = fixedLinkedHashMap.values().size();
// 統(tǒng)計(jì)其中的總和
int sum = fixedLinkedHashMap.values().stream().mapToInt(value -> value).sum();

基于Guava的EvictingQueue

引入maven依賴
<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>30.1.1-jre</version>
</dependency>
使用示例
// 初始化時指定大小
private final EvictingQueue<Integer> evictingQueue = EvictingQueue.create(LIST_SIZE);

// 添加元素
evictingQueue.add(MOCK_EXCEPTION_COUNT);

// 讀取元素
// 元素個數(shù)
size = evictingQueue.size();
// 統(tǒng)計(jì)其中的和
sum = evictingQueue.stream().mapToInt(value -> value).sum();

注意: 引入了目前(2021-07-12)最新的guava版本30.1.1-jre,EvictingQueue類還是標(biāo)記了@Beta纵柿。

基于Redis的list操作

示例在SpringBoot應(yīng)用中蜈抓,使用RedisTemplate。

主要基于Redis列表的三個操作昂儒。

  1. LPUSH:將元素插入頭部
  2. LTRIM: 對列表進(jìn)行裁剪沟使,可以指定起始位置
  3. LRANGE: 獲取列表指定范圍內(nèi)的元素
引入maven依賴
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
使用示例
// 初始化RedisTemplate
@Resource
private RedisTemplate<String, Integer> redisTemplate;


ListOperations<String, Integer> stringIntegerListOperations = redisTemplate.opsForList();
// LPUSH操作
stringIntegerListOperations.leftPush(REDIS_LIST_KEY, MOCK_EXCEPTION_COUNT);
// LTRIM
stringIntegerListOperations.trim(REDIS_LIST_KEY, 0, LIST_SIZE - 1);
// LRANGE操作
List<Integer> range = stringIntegerListOperations.range(REDIS_LIST_KEY, 0, LIST_SIZE - 1);

// 對結(jié)果操作
size = range.size();
sum = range.stream().mapToInt(value -> value).sum();

完整示例


@Service
@Slf4j
public class FixedListScheduler {

  private static final int LIST_SIZE = 10;

  private static final int MOCK_EXCEPTION_COUNT = 1;

  private static final String REDIS_LIST_KEY = "redis_fixed_list";

  private final FixedLinkedHashMap<String, Integer> fixedLinkedHashMap = new FixedLinkedHashMap<>(LIST_SIZE);

  private final EvictingQueue<Integer> evictingQueue = EvictingQueue.create(LIST_SIZE);

  @Resource
  private RedisTemplate<String, Integer> redisTemplate;

  @Scheduled(cron = "*/1 * * * * ?")
  public void schedule() {
    fixedLinkedHashMap.put(UUID.randomUUID().toString(), MOCK_EXCEPTION_COUNT);

    long size = fixedLinkedHashMap.values().size();
    int sum = fixedLinkedHashMap.values().stream().mapToInt(value -> value).sum();

    log.info("fixedLinkedHashMap size:{}, sum:{}", size, sum);
    evictingQueue.add(MOCK_EXCEPTION_COUNT);
    size = evictingQueue.size();
    sum = evictingQueue.stream().mapToInt(value -> value).sum();
    log.info("evictingQueue size:{}, sum:{}", size, sum);

    ListOperations<String, Integer> stringIntegerListOperations = redisTemplate.opsForList();
    stringIntegerListOperations.leftPush(REDIS_LIST_KEY, MOCK_EXCEPTION_COUNT);
    stringIntegerListOperations.trim(REDIS_LIST_KEY, 0, LIST_SIZE - 1);

    List<Integer> range = stringIntegerListOperations.range(REDIS_LIST_KEY, 0, LIST_SIZE - 1);
    if (!CollectionUtils.isEmpty(range)) {
      sum = range.stream().mapToInt(value -> value).sum();
      log.info("redis FixedList size:{}, sum:{}", range.size(), sum);
    }
  }
}

程序啟動一段時間后的日志,可以看到是滿足要求的渊跋。

2021-07-12 18:35:29.006  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : evictingQueue size:10, sum:10
2021-07-12 18:35:29.009  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : redis FixedList size:10, sum:10
2021-07-12 18:35:30.002  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : fixedLinkedHashMap size:10, sum:10
2021-07-12 18:35:30.002  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : evictingQueue size:10, sum:10
2021-07-12 18:35:30.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : redis FixedList size:10, sum:10
2021-07-12 18:35:31.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : fixedLinkedHashMap size:10, sum:10
2021-07-12 18:35:31.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : evictingQueue size:10, sum:10
2021-07-12 18:35:31.008  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : redis FixedList size:10, sum:10
2021-07-12 18:35:32.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : fixedLinkedHashMap size:10, sum:10
2021-07-12 18:35:32.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : evictingQueue size:10, sum:10
2021-07-12 18:35:32.009  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : redis FixedList size:10, sum:10
2021-07-12 18:35:33.002  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : fixedLinkedHashMap size:10, sum:10
2021-07-12 18:35:33.002  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : evictingQueue size:10, sum:10
2021-07-12 18:35:33.005  INFO 8622 --- [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler    : redis FixedList size:10, sum:10

總結(jié)

以上三種方式均可實(shí)現(xiàn)固定長度的list。FixedLinkedHashMap和EvictingQueue是基于內(nèi)存的拾酝,所以僅支持節(jié)點(diǎn)情況燕少。而基于Redis的list除了單節(jié)點(diǎn)情況,同樣可以在分布式情況使用蒿囤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末客们,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌底挫,老刑警劉巖恒傻,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異建邓,居然都是意外死亡盈厘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門官边,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沸手,“玉大人,你說我怎么就攤上這事注簿∑跫” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵滩援,是天一觀的道長栅隐。 經(jīng)常有香客問我,道長玩徊,這世上最難降的妖魔是什么租悄? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮恩袱,結(jié)果婚禮上泣棋,老公的妹妹穿的比我還像新娘。我一直安慰自己畔塔,他們只是感情好潭辈,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澈吨,像睡著了一般把敢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谅辣,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天修赞,我揣著相機(jī)與錄音,去河邊找鬼桑阶。 笑死柏副,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蚣录。 我是一名探鬼主播割择,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萎河!你這毒婦竟也來了荔泳?” 一聲冷哼從身側(cè)響起蕉饼,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎换可,沒想到半個月后椎椰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厦幅,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沾鳄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了确憨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译荞。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡休弃,死狀恐怖吞歼,靈堂內(nèi)的尸體忽然破棺而出塔猾,到底是詐尸還是另有隱情,我是刑警寧澤丈甸,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布糯俗,位于F島的核電站,受9級特大地震影響睦擂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顿仇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臼闻。 院中可真熱鬧鸿吆,春花似錦、人聲如沸述呐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黎泣。三九已至缤谎,卻和暖如春抒倚,著一層夾襖步出監(jiān)牢的瞬間坷澡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馅扣,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓差油,卻偏偏與公主長得像任洞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子交掏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 哇,今天2019年最后一天上班钱骂,實(shí)在沒心情擼代碼,感覺隔了好久沒寫博客了见秽,乘機(jī)寫點(diǎn)吧狰住≌偶回想2019實(shí)在是充實(shí)的一年...
    蔣仁勇閱讀 10,941評論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理催植,服務(wù)發(fā)現(xiàn),斷路器伦忠,智...
    卡卡羅2017閱讀 134,711評論 18 139
  • 1、安裝與配置 1.1 安裝 kafka依賴于ZooKeeper昆码,如果以單機(jī)模式調(diào)試kafka邻储,需要確保本機(jī)已經(jīng)安...
    冰河winner閱讀 765評論 0 4
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒吨娜。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了宦赠,難過就哭了米母。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,350評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者毡琉,不喜歡去冒險,但是人生放棄了冒險桅滋,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 6,059評論 0 4