java-8 - Java 8 Using Stream,查找最新状态,如果'F'替换来自状态'R'的相应原因
问题描述
我有一个字段名称如下的对象列表,我正在尝试从状态“R”的相应原因字段中替换状态“F”的原因字段。仅当每个发布者的时间戳的最新状态为“F”时才需要执行此操作
auditedBy status time Reason
api-a S 10:20 'A1'
api-a R 10:25 'A2'
api-a F 10:30 'A3'
-----
api-b S 10:30 'B1'
api-b S 10:25 'B2'
api-b S 10:20 'B3'
-----
api-c S 10:20 'C1'
api-c S 10:30 'C1'
api-c F 10:40 'C3'
所以上述数据的最终输出将是
auditedBy status time Reason
api-a S 10:20 'A1'
api-a R 10:25 'A2'
api-a F 10:30 'A2' ******
api-b S 10:30 'B1'
api-b S 10:25 'B2'
api-b S 10:20 'B3'
api-c S 10:20 'C1'
api-c S 10:30 'C1'
api-c F 10:40 'C3'
我将在下面提供我的实现,如果需要任何改进,请告诉我。
我将创建具有最新状态的地图,因为“F”地图将具有
api-a -> api-a,F,10:30,'A3' api-c -> api-c,F,10:40,'C3'
然后我将创建地图,这将包含状态为“R”的记录,用于之前地图中的那些记录。
地图上面会有。api-a -> api-a,R,10:25,'A2'
我将从两张地图的原始列表中更改原因。
private List<DetailRecord> changeReasonFunction(List<DetailRecord> records) {
Map<String, DetailRecord> eventsFailed = records.stream()
.collect(toMap(DetailRecord::getAuditedBy, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(DetailRecord::getAuditTimestamp))))
.values()
.stream().filter(detRec -> FAILED.getStatus().equals(detRec.getStatus()))
.collect(toMap(DetailRecord::getAuditedBy, Function.identity()));
Map<String, DetailRecord> retryRecordForFailedEvents = records.stream()
.filter(rec -> eventsFailed.keySet().contains(rec.getAuditedBy()))
.filter(rec -> FAILED_RECOVERABLE_ERROR.getStatus().equals(rec.getStatus()))
.collect(toMap(DetailRecord::getAuditedBy, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(DetailRecord::getAuditTimestamp))));
records.forEach(rec -> {
if (eventsFailed.containsKey(rec.getAuditedBy()) &&
eventsFailed.get(rec.getAuditedBy()).getAuditTimestamp()
.compareTo(rec.getAuditTimestamp()) == 0) {
DetailRecord obj = retryRecordForFailedEvents.get(rec.getAuditedBy());
if (obj != null) {
rec.setExceptionReason(obj.getExceptionReason());
rec.setExceptionDetail(obj.getExceptionDetail());
}
}
});
return records;
}
解决方案
groupingBy
你可以像这样用收集器试试这个:
private List<DetailRecord> changeReasonFunction(List<DetailRecord> records) {
return records.stream()
.collect(Collectors.groupingBy(DetailRecord::getAuditedBy))
.values().stream()
.flatMap(list -> {
Optional<DetailRecord> maxRecord = list.stream().max(Comparator.comparing(DetailRecord::getTime));
if (maxRecord.isPresent()
&& maxRecord.get().getStatus().equals("F")
&& list.stream().anyMatch(detailRecord -> detailRecord.getStatus().equals("R"))) {
maxRecord.get().setReason(
list.stream()
.filter(detailRecord -> detailRecord.getStatus().equals("R"))
.findAny().get().getReason());
}
return list.stream();
}).collect(Collectors.toList());
}
您需要根据您使用的数据类型对其进行修改。我用了:
public class DetailRecord {
private String auditedBy;
private String status;
private Instant time;
private String reason;
}
测试:
List<DetailRecord> l = new ArrayList<>();
l.add(new DetailRecord("api-a", "S", Instant.parse("2019-01-01T10:20:00.00Z"), "A1"));
l.add(new DetailRecord("api-a", "R", Instant.parse("2019-01-01T10:25:00.00Z"), "A2"));
l.add(new DetailRecord("api-a", "F", Instant.parse("2019-01-01T10:30:00.00Z"), "A3"));
l.add(new DetailRecord("api-b", "S", Instant.parse("2019-01-01T10:30:00.00Z"), "B1"));
l.add(new DetailRecord("api-b", "S", Instant.parse("2019-01-01T10:25:00.00Z"), "B2"));
l.add(new DetailRecord("api-b", "S", Instant.parse("2019-01-01T10:20:00.00Z"), "B3"));
l.add(new DetailRecord("api-c", "S", Instant.parse("2019-01-01T10:20:00.00Z"), "C1"));
l.add(new DetailRecord("api-c", "S", Instant.parse("2019-01-01T10:30:00.00Z"), "C1"));
l.add(new DetailRecord("api-c", "F", Instant.parse("2019-01-01T10:40:00.00Z"), "C3"));
System.out.println(changeReasonFunction(l));
输出如您所料。
推荐阅读
- django - 为什么我在尝试为儿童用户创建文章时会出错?
- javascript - 如何触发另一个函数内部的函数
- reactjs - 工具提示位置材料ui iin ReactJs应用程序不起作用
- rest - 如何从 CA Service Desk Manager REST API 中的模板创建标准更改?
- android - 如果我在 Google Play 上取消发布我的应用程序,我是否仍需要更新我的应用程序以支持新的 Android 版本?
- html - 为什么 :last-child 选择器停止在添加不同的 div 时应用
- flutter - Flutter 包管理?
- javascript - NVDA 箭头导航仅适用于高图表中的 alt 键
- postgresql - 如何在 Pgadmin4 中使用 \df 和 \sf 命令
- c++ - 模板参数推导不适用于函数模板