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


Posted in Java/Android onJuly 15, 2021

前言

最近团队有同学在开发中,遇到一个需求,统计最近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列表的三个操作。

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

引入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);

// 对结果操作
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

总结

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

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

Java/Android 相关文章推荐
ConstraintValidator类如何实现自定义注解校验前端传参
Jun 18 Java/Android
死磕 java同步系列之synchronized解析
Jun 28 Java/Android
每日六道java新手入门面试题,通往自由的道路
Jun 30 Java/Android
spring boot中nativeQuery的用法
Jul 26 Java/Android
Java spring定时任务详解
Oct 05 Java/Android
springmvc直接不经过controller访问WEB-INF中的页面问题
Feb 24 Java/Android
关于ObjectUtils.isEmpty() 和 null 的区别
Feb 28 Java/Android
SpringBoot+Redis实现布隆过滤器的示例代码
Mar 17 Java/Android
Java字符串逆序方法详情
Mar 21 Java/Android
Spring Boot 底层原理基础深度解析
Apr 03 Java/Android
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
Apr 24 Java/Android
Spring boot admin 服务监控利器详解
Aug 05 Java/Android
gateway网关接口请求的校验方式
spring cloud gateway中如何读取请求参数
Spring Cloud Gateway去掉url前缀
Jul 15 #Java/Android
小程序与后端Java接口交互实现HelloWorld入门
Java生成读取条形码和二维码的简单示例
Jul 09 #Java/Android
详细了解java监听器和过滤器
Jul 09 #Java/Android
Java使用jmeter进行压力测试
You might like
php内嵌函数用法实例
2015/03/20 PHP
JQury slideToggle闪烁问题及解决办法
2011/07/05 Javascript
JavaScript返回网页中超链接数量的方法
2015/04/03 Javascript
javascript实现汉字转拼音代码分享
2015/04/20 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
vue分页组件table-pagebar使用实例解析
2020/11/15 Javascript
Vue.js实现一个自定义分页组件vue-paginaiton
2016/09/05 Javascript
微信小程序 wx.request(接口调用方式)详解及实例
2016/11/23 Javascript
jQuery Password Validation密码验证
2016/12/30 Javascript
jQuery实现碰到边缘反弹的动画效果
2018/02/24 jQuery
iview table render集成switch开关的实例
2018/03/14 Javascript
vue短信验证性能优化如何写入localstorage中
2018/04/25 Javascript
layer.open 按钮的点击事件关闭方法
2018/08/17 Javascript
Node.js操作系统OS模块用法分析
2019/01/04 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
vue-cli+axios实现文件上传下载功能(下载接收后台返回文件流)
2019/05/10 Javascript
vue.js购物车添加商品组件的方法
2019/09/17 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
2020/04/01 jQuery
Python利用递归和walk()遍历目录文件的方法示例
2017/07/14 Python
Python回文字符串及回文数字判定功能示例
2018/03/20 Python
用Python写一段用户登录的程序代码
2018/04/22 Python
python打包成so文件过程解析
2019/09/28 Python
用python求一重积分和二重积分的例子
2019/12/06 Python
Django后端按照日期查询的方法教程
2021/02/28 Python
HTML5拖拽文件到浏览器并实现文件上传下载功能代码
2013/06/06 HTML / CSS
HTML5 source标签:媒介元素定义媒介资源
2018/01/29 HTML / CSS
意大利体育用品网上商城:Nencini Sport
2016/08/18 全球购物
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
联想英国官网:Lenovo英国
2019/07/17 全球购物
sleep()方法和wait()方法的区别是什么
2012/11/17 面试题
高中自我评价分享
2013/12/05 职场文书
怎样写离婚协议书
2014/09/10 职场文书
教师批评与自我批评(群众路线)
2014/10/15 职场文书
六一领导慰问欢迎词
2015/01/26 职场文书
mysql备份策略的实现(全量备份+增量备份)
2021/07/07 MySQL