首页 > 解决方案 > 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'

我将在下面提供我的实现,如果需要任何改进,请告诉我。

  1. 我将创建具有最新状态的地图,因为“F”地图将具有

    api-a -> api-a,F,10:30,'A3' api-c -> api-c,F,10:40,'C3'

  2. 然后我将创建地图,这将包含状态为“R”的记录,用于之前地图中的那些记录。
    地图上面会有。

    api-a -> api-a,R,10:25,'A2'

  3. 我将从两张地图的原始列表中更改原因。

    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;
    }

标签: java-8hashmapjava-streamgrouping

解决方案


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

输出如您所料。


推荐阅读