新闻中心
J*a中计算列表数据中按条件分组的连续失败时长

本教程详细介绍了如何在j*a中处理包含时间序列和状态信息的列表数据,以计算每个实体(如用户)的累积失败时长。通过将数据按实体分组,并利用j*a stream api或第三方seq库进行排序和有状态遍历,精确地统计从“失败”状态开始到下一个“成功”状态结束的持续时间。文章提供了具体的代码示例,并讨论了实现细节及注意事项。
在现代数据处理中,我们经常需要从一系列事件记录中提取有意义的聚合信息。一个常见场景是,给定一个包含实体名称、事件日期和状态(例如“成功”或“失败”)的列表,我们需要计算每个实体在特定条件下的累计时长。本教程将以计算“连续失败时长”为例,详细讲解如何使用J*a的Stream API以及第三方库Seq来高效解决此类问题。
问题描述
假设我们有一组按时间顺序排列的事件记录,每条记录包含一个实体名称(name)、事件发生的年份(date)和事件状态(status,可以是"success"或"fail")。我们需要为每个实体计算其总的“失败时长”。失败时长定义为:从一个“失败”状态开始,到紧随其后的第一个“成功”状态结束的时间跨度。如果在一个失败周期中出现多个连续的失败事件,它们将被视为同一失败周期的延续。
示例数据:
[
{"name":"john", "date":2015, "status":"success"},
{"name":"john", "date":2013, "status":"fail"},
{"name":"chris", "date":2013, "status":"success"},
{"name":"john", "date":2012, "status":"fail"},
{"name":"john", "date":2009, "status":"success"},
{"name":"chris", "date":2007, "status":"fail"},
{"name":"john", "date":2005, "status":"fail"},
]根据上述定义,对于john:
立即学习“J*a免费学习笔记(深入)”;
微软爱写作
微软出品的免费英文写作/辅助/批改/评分工具
130
查看详情
- 2005年失败,下一个成功是2009年,失败时长为 2009 - 2005 = 4 年。
- 2012年失败,2013年再次失败(视为同一失败周期),下一个成功是2015年,失败时长为 2015 - 2012 = 3 年。
- john的总失败时长为 4 + 3 = 7 年。
对于chris:
- 2007年失败,下一个成功是2013年,失败时长为 2013 - 2007 = 6 年。
- chris的总失败时长为 6 年。
数据模型定义
为了更好地组织和处理数据,我们首先定义一个J*a类来表示每条记录,而不是直接使用HashMap。这提供了更好的类型安全性和代码可读性。
public class Record {
public String name;
public Integer date; // 使用Integer表示年份
public String status;
public Record(String name, Integer date, String status) {
this.name = name;
this.date = date;
this.status = status;
}
@Override
public String toString() {
return "Record{" +
"name='" + name + '\'' +
", date=" + date +
", status='" + status + '\'' +
'}';
}
}核心计算逻辑
解决此类问题的关键在于对数据进行分组和按时间排序,并在遍历过程中维护一个状态。具体步骤如下:
- 按实体名称分组:首先,将所有记录根据其name字段进行分组。这样,我们可以独立地处理每个实体的事件序列。
- 组内按日期排序:对于每个实体组,必须将其内部的记录按照date字段升序排序。这是确保计算逻辑正确性的前提,因为失败时长的计算依赖于事件的先后顺序。
-
有状态遍历计算:
- 在遍历每个实体排序后的记录时,我们需要维护一个变量来记录当前是否处于一个失败周期中,以及该失败周期的起始日期。我们可以使用一个Integer类型的变量lastFailDate,初始值为null。
- 当遇到一条状态为"fail"的记录时:
- 如果lastFailDate为null,表示这是一个新的失败周期的开始,我们将当前记录的date赋值给lastFailDate。
- 如果lastFailDate不为null,表示失败周期正在持续,我们不需要更新lastFailDate(因为我们只关心失败的起始点)。
- 当遇到一条状态为"success"的记录时:
- 如果lastFailDate不为null,表示当前有一个未结束的失败周期。此时,计算当前成功记录的date与lastFailDate之差,作为本次失败的时长,并将其累加到该实体的总失败时长
中。 - 计算完成后,将lastFailDate重置为null,表示该失败周期已经结束。
- 如果lastFailDate不为null,表示当前有一个未结束的失败周期。此时,计算当前成功记录的date与lastFailDate之差,作为本次失败的时长,并将其累加到该实体的总失败时长
- 如果lastFailDate为null,则忽略当前成功记录,因为它没有前置的失败周期。
使用J*a Stream API实现
J*a 8引入的Stream API为集合处理提供了强大而灵活的工具。我们可以利用它来实现上述逻辑。
import j*a.util.List;
import j*a.util.Map;
import j*a.util.Comparator;
import j*a.util.stream.Collectors;
public class FailureDurationCalculator {
public static Map<String, Integer> calculateFailureDurationWithStream(List<Record> records) {
return records.stream()
// 1. 按名称分组:将所有记录根据其name字段分组,得到Map<String, List<Record>>
.collect(Collectors.groupingBy(r -> r.name))
.entrySet().stream() // 将Map的entrySet转换为Stream,以便进一步处理每个分组
// 2. 对每个分组计算失败时长,并收集到最终的Map<String, Integer>中
.collect(Collectors.toMap(Map.Entry::getKey, entry -> {
// 使用数组作为可变变量,以在Lambda表达式中存储上一次失败的日期。
// Stream操作通常是无状态的,但这里需要维护一个跨记录的状态。
Integer[] lastFailDate = new Integer[]{null};
return entry.getValue().stream()
// 3. 对每个分组内的记录按日期升序排序
.sorted(Comparator.comparing(r -> r.date))
.mapToInt(record -> {
if ("fail".equals(record.status) && lastFailDate[0] == null) {
// 遇到失败,且当前没有正在进行的失败期,记录失败开始日期
lastFailDate[0] = record.date;
} else if ("success".equals(record.status) && lastFailDate[0] != null) {
// 遇到成功,且有正在进行的失败期,计算时长
int duration = record.date - lastFailDate[0];
lastFailDate[0] = null; // 重置失败开始日期,表示该失败周期已结束
return duration;
}
return 0; // 其他情况(如连续失败、成功后无失败等)不产生时长
})
.sum(); // 累加所有计算出的失败时长,得到该实体的总失败时长
}));
}
public static void main(String[] args) {
List<Record> records = List.of(
new Record("john", 2015, "success"),
new Record("john", 2013, "fail"),
new Record("chris", 2013, "success"),
new Record("john", 2012, "fail"),
new Record("john", 2009, "success"),
new Record("chris", 2007, "fail"),
new Record("john", 2005, "fail")
);
Map<String, Integer> failureDurations = calculateFailureDurationWithStream(records);
System.out.println("使用Stream API计算的失败时长: " + failureDurations); // 预期输出: {chris=6, john=7}
}
}以上就是J*a中计算列表数据中按条件分组的连续失败时长的详细内容,更多请关注其它相关文章!
# 自定义
# 营销推广的手段包括
# 锦州本地网站优化哪里好
# 岑巩县营销推广报价
# 义乌网站建设招标公示网
# seo高权重怎么排名
# 河南网站建设系统介绍
# seo排名异常
# 百度关键词营销推广公司
# 橡塑网站优化策略
# 陕西seo服务公司
# 错误信息
# 第三方
# 不为
# java
# 此类
# 子类
# 升序
# 遍历
# 微软
# 时长
# red
# java类
# 排列
# 代码可读性
# stream
# ai
# 工具
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法
苹果手机如何防止被恶意App追踪
J*a应用程序首次运行自动创建文件与目录的最佳实践
Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】
126邮箱手机版登录官网2026_126手机邮箱免费入口最新
css滚动动画效果怎么实现_使用Animate.css滚动触发动画类
支付宝如何管理隐私设置_支付宝隐私保护的配置技巧
PyTorch模型训练效果不佳?深入剖析常见错误与调试技巧
如何将HTML表格多行数据保存到Google Sheet
C++如何实现异步操作_C++11使用std::future和std::async进行异步编程
qq邮箱发邮件给国外发不出去_QQ邮箱国际邮件发送失败原因与解决
J*aScript中高效管理与清空动态列表:避免循环陷阱
聚水潭ERP登录页面入口 聚水潭ERP官网登录界面
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读
Win10快速启动功能利弊分析 Win10开启或关闭快速启动教程【技巧】
利用Bokeh CustomJS动态控制DataTable列可见性
PPT平滑切换怎么做 PPT炫酷“平滑”切换动画制作教程【必学】
神经网络二分类模型训练异常:高损失与完美验证准确率的排查与修正
Win11 BitLocker密码忘了怎么办 Win11找回BitLocker恢复密钥方法【解决】
不同用户不同价格! 索尼开启账户个性化定价测试
J*a 递归快速排序中静态变量的状态管理与陷阱
AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看
小米14应用无法联网原因分析_小米14网络权限修复
如何在 Excel Online 和 Google 表格中更改日期格式
qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程
KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法
Win10如何开启蓝牙功能_Windows10找不到蓝牙开关解决方法
使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战
优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题
Python:递归比较文件夹内容并找出特定类型文件的差异
Sublime怎么配置Nim语言环境_Sublime Nim代码高亮与补全
Sublime Text怎么显示空格和制表符_Sublime显示不可见字符设置
c++20的std::jthread是什么_c++可中断线程与RAII式管理
Mac怎么锁定备忘录_Mac备忘录加密设置教程
冬*霸灯泡不亮怎么办_浴霸取暖灯一盏不亮的灯座清洁修复法
Python模块化编程:有效管理依赖与避免循环引用
css子元素高度不一致导致布局错位怎么办_使用align-items:stretch解决高度差异
Yandex官网搜索引擎免登录_俄罗斯Yandex一键直达入口
想当下一个《2077》?《心之眼》Steam评价升至"多半好评"
深入理解J*aScript Promise异步执行与微任务队列
曝R星经典之作开发图 设计简陋但信息密集!
正确连接J*aScript到HTML实现可点击图片与自定义事件处理
手机屏幕碎了但能正常使用怎么办 手机外屏碎裂的修复建议
b站如何看历史记录_b站观看历史找回方法
高德地图总提示网络异常怎么办 高德地图离线导航设置与网络排查方法
J*aScript中安全有效地处理localStorage字符串数据
2025AO3夸克浏览器通道_AO3手机HTTPS安全入口分享
Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法
ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接


2025-12-12
浏览次数:次
返回列表
中。