I have a List of Object with field names as below, I'm trying to replace the reason field of the 
status 'F' from the corresponding reason field from status 'R'. This needs to be performed only when the latest status by timestamp per publisher has a status of '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'

```

so the final output of the above data will be 

```
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'

```

I'll provide my implementation below please let me know if any improvements is needed.

1. I'll create map with the latest status as 'F' 
Map will have 

> 
> api-a -> api-a,F,10:30,'A3'
>  api-c -> api-c,F,10:40,'C3'
> 
> 
>
2. Then I'll create map, this will contain records
with status as 'R' for those records in previous map.  

Map above will have.

> 
> api-a -> api-a,R,10:25,'A2'
> 
> 
>
3. I'll change the reason from the original list from both the maps.

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

```