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 相关文章推荐
Java Shutdown Hook场景使用及源码分析
Jun 15 Java/Android
Spring Cache和EhCache实现缓存管理方式
Jun 15 Java/Android
Java并发编程之详解CyclicBarrier线程同步
Jun 23 Java/Android
springcloud之Feign超时问题的解决
Jun 24 Java/Android
关于Spring配置文件加载方式变化引发的异常详解
Jan 18 Java/Android
Netty客户端接入流程NioSocketChannel创建解析
Mar 25 Java/Android
Java 深入探究讲解简单工厂模式
Apr 07 Java/Android
Qt数据库应用之实现图片转pdf
Jun 01 Java/Android
Android 中的类文件和类加载器详情
Jun 05 Java/Android
前端与RabbitMQ实时消息推送未读消息小红点实现示例
Jul 23 Java/Android
IDEA中sout快捷键无效问题的解决方法
Jul 23 Java/Android
Spring Boot实现文件上传下载
Aug 14 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 和 MySQL 基础教程(一)
2006/10/09 PHP
URL Rewrite的设置方法
2007/01/02 PHP
php adodb介绍
2009/03/19 PHP
使用Thinkphp框架开发移动端接口
2015/08/05 PHP
JS(jQuery)实现聊天接收到消息语言自动提醒功能详解【提示“您有新的消息请注意查收”】
2019/04/16 PHP
javascript知识点收藏
2007/02/22 Javascript
JS拖动技术 关于setCapture使用
2010/12/09 Javascript
JavaScript中的call方法和apply方法使用对比
2015/08/12 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
2015/08/26 Javascript
jQuery动画效果图片轮播特效
2016/01/12 Javascript
JS实现针对给定时间的倒计时功能示例
2017/04/11 Javascript
JS查找数组中重复元素的方法详解
2017/06/14 Javascript
AngularJS实现的简单拖拽功能示例
2018/01/02 Javascript
Vue 源码分析之 Observer实现过程
2018/03/29 Javascript
详解vue-cli 本地开发mock数据使用方法
2018/05/29 Javascript
vue组件间的参数传递实例详解
2019/04/26 Javascript
[03:42]2016国际邀请赛中国区预选赛首日现场玩家采访
2016/06/26 DOTA
Python中optionParser模块的使用方法实例教程
2014/08/29 Python
python中常用检测字符串相关函数汇总
2015/04/15 Python
python动态加载包的方法小结
2016/04/18 Python
详解python3中socket套接字的编码问题解决
2017/07/01 Python
一篇文章读懂Python赋值与拷贝
2018/04/19 Python
python入门:这篇文章带你直接学会python
2018/09/14 Python
python实现坦克大战游戏 附详细注释
2020/03/27 Python
使用 django orm 写 exists 条件过滤实例
2020/05/20 Python
python爬虫 requests-html的使用
2020/11/30 Python
详解CSS3选择器:nth-child和:nth-of-type之间的差异
2017/09/18 HTML / CSS
详解css3使用transform出现字体模糊的解决办法
2020/10/16 HTML / CSS
联想中国官方商城:Lenovo China
2017/10/18 全球购物
介绍一下XMLHttpRequest对象
2012/02/12 面试题
转党组织关系介绍信
2014/01/08 职场文书
文明餐桌行动实施方案
2014/02/19 职场文书
绿色出行口号
2014/06/18 职场文书
领导干部个人对照检查材料(群众路线)
2014/09/26 职场文书
《飘》英文读后感五篇
2019/10/11 职场文书
详解php中流行的rpc框架
2021/05/29 PHP