java固定大小队列的几种实现方式详解

目录前言基于Hutool中的FixedLinkedHashMap基于Guava的EvictingQueue基于Redis的list操作总结

前言

最近团队有同学在开发中,遇到一个需求,统计最近10次的异常次数,咨询有没有类似的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,可以按照自己的业务需求填写fixedLinkedHashMap.put(UUID.randomUUID().toString(), 1);// 读取操作// 获取元素个数long size = fixedLinkedHashMap.values().size();// 统计其中的总和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);// 读取元素// 元素个数size = evictingQueue.size();// 统计其中的和sum = evictingQueue.stream().mapToInt(value -> value).sum();

注意: 引入了目前(2021-07-12)最新的guava版本30.1.1-jre,EvictingQueue类还是标记了@Beta。

基于Redis的list操作

示例在SpringBoot应用中,使用RedisTemplate。

主要基于Redis列表的三个操作。

    LPUSH:将元素插入头部 LTRIM: 对列表进行裁剪,可以指定起始位置 LRANGE: 获取列表指定范围内的元素

引入maven依赖

<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

使用示例

// 初始化RedisTemplate@Resourceprivate RedisTemplate<String, Integer> redisTemplate;ListOperations<String, Integer> stringIntegerListOperations = redisTemplate.opsForList();// LPUSH操作stringIntegerListOperations.leftPush(REDIS_LIST_KEY, MOCK_EXCEPTION_COUNT);// LTRIMstringIntegerListOperations.trim(REDIS_LIST_KEY, 0, LIST_SIZE - 1);// LRANGE操作List<Integer> range = stringIntegerListOperations.range(REDIS_LIST_KEY, 0, LIST_SIZE - 1);// 对结果操作size = range.size();sum = range.stream().mapToInt(value -> value).sum();

完整示例

@Service@Slf4jpublic 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:102021-07-12 18:35:29.009 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : redis FixedList size:10, sum:102021-07-12 18:35:30.002 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : fixedLinkedHashMap size:10, sum:102021-07-12 18:35:30.002 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : evictingQueue size:10, sum:102021-07-12 18:35:30.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : redis FixedList size:10, sum:102021-07-12 18:35:31.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : fixedLinkedHashMap size:10, sum:102021-07-12 18:35:31.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : evictingQueue size:10, sum:102021-07-12 18:35:31.008 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : redis FixedList size:10, sum:102021-07-12 18:35:32.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : fixedLinkedHashMap size:10, sum:102021-07-12 18:35:32.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : evictingQueue size:10, sum:102021-07-12 18:35:32.009 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : redis FixedList size:10, sum:102021-07-12 18:35:33.002 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : fixedLinkedHashMap size:10, sum:102021-07-12 18:35:33.002 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : evictingQueue size:10, sum:102021-07-12 18:35:33.005 INFO 8622 — [pool-2-thread-1] com.yichao.myblogs.FixedListScheduler : redis FixedList size:10, sum:10

总结

以上三种方式均可实现固定长度的list。FixedLinkedHashMap和EvictingQueue是基于内存的,所以仅支持节点情况。而基于Redis的list除了单节点情况,同样可以在分布式情况使用。

到此这篇关于java固定大小队列的文章就介绍到这了,更多相关java固定大小队列内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

思想如钻子,必须集中在一点钻下去才有力量

java固定大小队列的几种实现方式详解

相关文章:

你感兴趣的文章:

标签云: