当前位置: 首页 > article >正文

java如何利用流式计算筛选出同一天时间最新的一条数据

有时候用sql做自联接或者groupBy不方便,可以选择java的流式计算

两种方案

1:

// 身体肌肉率 Muscle
		List<KpiVO> lastMuscle = allDevicesVOS.stream()
			.filter(device -> StringUtil.isNotBlank(device.getMuscle())) // 过滤出身体肌肉率都不为 null 的记录
			.collect(Collectors.groupingBy(device -> device.getCheckTime().toLocalDate())) // 按 LocalDate 分组
			.values().stream()
			.map(devices -> devices.stream()
				.max((d1, d2) -> d1.getCheckTime().compareTo(d2.getCheckTime())) // 找到每组最新的记录
				.orElse(null)) // 如果某组为空,返回 null
			.filter(device -> device != null) // 过滤掉 null 值
			.map(device -> {
					KpiVO kpiVO = new KpiVO();
					kpiVO.setCheckTimes(device.getCheckTime().toLocalDate().toString());
					kpiVO.setLast(device.getMuscle());
					return kpiVO;
				}
			)
			.sorted((k1, k2) -> k1.getCheckTimes().compareTo(k2.getCheckTimes())) // 按 checkTimes 正序排列
			.collect(Collectors.toList());// 转换回 List<KpiVO>

2:

// 使用 Java 8 Stream API 处理结果
		List<LocalDate> result = checkTimes.stream()
			.collect(Collectors.groupingBy(e -> e.getCheckTime().toLocalDate(),  // 按日期分组
				Collectors.maxBy((e1, e2) -> e1.getCheckTime().compareTo(e2.getCheckTime()))  // 选择每个日期中时间最晚的记录
			))
			.values()
			.stream()
			.map(Optional::get)
			.sorted(Comparator.comparing(NormBasicDeviceDataEntity::getCheckTime).reversed())  // 对日期进行降序排序
			.map( entity -> {return entity.getCheckTime().toLocalDate();})
			.collect(Collectors.toList());

两种方案的区别在于

两段代码中都有groupingBy操作,特别是第二段如何使用maxBy来选择每个日期中的“最晚记录”。

第二段代码解析

 

List<LocalDate> result = checkTimes.stream() .collect(Collectors.groupingBy(e -> e.getCheckTime().toLocalDate(), // 按日期分组 Collectors.maxBy((e1, e2) -> e1.getCheckTime().compareTo(e2.getCheckTime())) // 选择每个日期中时间最晚的记录 )) .values() .stream() .map(Optional::get) .sorted(Comparator.comparing(NormBasicDeviceDataEntity::getCheckTime).reversed()) // 对日期进行降序排序 .map(entity -> { return entity.getCheckTime().toLocalDate(); }) .collect(Collectors.toList());

这段代码的核心是在分组操作中使用了maxBy,让我们一步一步来分析。

1. groupingBy + maxBy

 

Collectors.groupingBy(e -> e.getCheckTime().toLocalDate(), Collectors.maxBy((e1, e2) -> e1.getCheckTime().compareTo(e2.getCheckTime())))

  • 分组依据: 这部分和前面相同,e -> e.getCheckTime().toLocalDate()是按每个元素(checkTime)的日期部分(LocalDate)进行分组。

  • maxBy: 关键的区别在于Collectors.maxBy,它并不是简单地将所有元素放入一个集合中,而是用于选择每个分组中“最大”的元素,这个“最大”是根据你给定的比较器来确定的。

    • maxBy((e1, e2) -> e1.getCheckTime().compareTo(e2.getCheckTime()))表示按时间(checkTime)比较,并选择每个分组中时间最晚的那个元素。
    • 由于是按时间升序排序(compareTo方法的返回值),因此maxBy返回的将是每个日期中最新的记录

    结果会是一个Map<LocalDate, Optional<NormBasicDeviceDataEntity>>,其中每个键(日期)对应一个Optional<NormBasicDeviceDataEntity>,表示每个日期的最新设备数据记录。

2. .values().stream()

  • values()会返回一个Collection<Optional<NormBasicDeviceDataEntity>>,这个集合是按日期分组后,每个日期组内最新的NormBasicDeviceDataEntity对象。
  • 通过.stream()转化为流,可以继续后续操作。

3. .map(Optional::get)

  • Optional::get会从每个Optional<NormBasicDeviceDataEntity>中提取出实际的NormBasicDeviceDataEntity对象(假设每个Optional不为空)。

4. .sorted(Comparator.comparing(NormBasicDeviceDataEntity::getCheckTime).reversed())

  • 按照每个NormBasicDeviceDataEntitycheckTime降序排序(reversed()),确保结果是按照时间从最新到最旧排列。

5. .map(entity -> entity.getCheckTime().toLocalDate())

  • 最后将每个NormBasicDeviceDataEntitycheckTime转换为LocalDate,即提取出日期部分。

6. collect(Collectors.toList())

  • 最终,结果被收集到一个List<LocalDate>中。

主要区别:groupingBymaxBy的结合 vs. 单纯的groupingBy

  • groupingBy + maxBy:
    • 在每个分组内使用maxBy来找到最大(最新)的记录。这意味着对于每个日期,我们只保留时间最晚的记录,而不是所有记录。
    • 结果是一个Map<LocalDate, Optional<NormBasicDeviceDataEntity>>,每个日期对应一个Optional,表示日期下的最新设备数据。
  • 单纯的groupingBy:
    • 单纯的groupingBy只会将数据根据某个条件分组,不会对每组数据做任何筛选或操作。因此,它返回的是Map<LocalDate, List<Device>>,其中每个日期对应一个包含该日期所有设备的列表。
    • 没有maxBy的情况下,每个日期下的所有记录都会保留,并没有进行筛选。

总结对比

  • 第一种方法(使用groupingBy后再用max)对每个分组中的数据进行了筛选,选出每个日期下的最新记录。
  • 第二种方法(使用groupingBymaxBy)使用maxBy直接在分组时就筛选出每个日期组中的最新记录,避免了后续的手动筛选。

http://www.kler.cn/a/400003.html

相关文章:

  • 刘艳兵-DBA036-Oracle数据库中的触发器(Trigger)可以在以下哪种情况下自动执行?
  • Ansible内置模块之known_hosts
  • 如何在 Ubuntu 上安装 Emby 媒体服务器
  • 探索美赛:从准备到挑战的详细指南
  • WEB服务器实现(药品商超)
  • SpringBoot+React养老院管理系统 附带详细运行指导视频
  • 深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度
  • 【鸿蒙开发】第十一章 Stage模型应用组件-任务Mission
  • MTU-内核态(数据链路层或网络接口上能够传输的最大数据包大小)
  • uniapp开发微信小程序笔记3-全局配置、导航栏配置、tabBar配置
  • [N1CTF 2018]eating_cms
  • uni-app项目搭建(ts+Vue3+pinia+vite)
  • StructuredStreaming (二)——kafka
  • Docker: ubuntu系统下Docker的安装
  • 免费开源!DBdoctor推出开源版系统诊断工具systool
  • Android屏幕横竖屏切换和生命周期
  • Hadoop 3.x 新特性详解
  • 【数据分享】中国渔业统计年鉴(1979-2024) pdf
  • GaussDB性能调优
  • 机器学习—偏差或方差与神经网络
  • 基于 AI 智能名片 2 + 1 链动模式商城小程序的立体连接营销策略研究
  • 问:Spring MVC DispatcherServlet流程步骤梳理
  • go 学习网站,go例子 go demo go学习视频
  • 基于Canny边缘检测和轮廓检测
  • 版本控制【Git Bash】【Gitee】
  • Django5 2024全栈开发指南(一):框架简介、环境搭建与项目结构