У меня есть список типа объекта - TrackingMessage, который содержит дату. Список может содержать 5 - несколько тысяч записей.
Мне нужно просмотреть этот список, сравнивая каждую дату, чтобы найти, какая из них ближе всего к минуте. Список может содержать 3 или 4 записи в течение минуты, поэтому ему нужно найти ближайшую к минуте запись, а затем округлить до ближайшей минуты.
, т. Е. 12:45:22, 12:45:35,12: 45: 15
В приведенном выше небольшом примере было бы выбрано значение 12: 45: 15 , как наиболее близкое к минуте, перед округлением до ближайшей минуты - 12: 45: 00 .
Код, который у меня сейчас есть, выглядит следующим образом:
Метод, который возвращает список отсортированных и округленных сообщений на основе времени
private List<TrackingMessage> findTrackingMessageDatesToNearestMinute(List<TrackingMessage> filteredTrackingMessages) {
return filteredTrackingMessages.stream()
.sorted(orderByClosestToMinute)
.filter(JourneyServiceUtil.distinctByKey(x -> roundToClosestMinute(x)))
.sorted(comparing(TrackingMessage::getEventTime))
.collect(Collectors.toList());
}
В поток передан компаратор
public Comparator<TrackingMessage> orderByClosestToMinute = (tm1, tm2) -> {
LocalDateTime roundedTrackingMessage1 = roundToClosestMinute(tm1);
LocalDateTime roundedTrackingMessage2 = roundToClosestMinute(tm2);
Duration tm1Duration = Duration.between(DateTimeUtils.toLocalDateTime(tm1.getEventTime()), roundedTrackingMessage1).abs();
Duration tm2Duration = Duration.between(DateTimeUtils.toLocalDateTime(tm2.getEventTime()), roundedTrackingMessage2).abs();
return tm1Duration.compareTo(tm2Duration);
};
Функция округления времени до ближайшей минуты
private LocalDateTime roundToClosestMinute(TrackingMessage trackingMessage) {
return DateTimeUtils.toLocalDateTime(DateUtils.round(trackingMessage.getEventTime(), Calendar.MINUTE));
}
Функция удаления дубликатов
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
Теперь этот код вроде работает, но ответ от возврата этого кода выглядит следующим образом:
{
"status": "success",
"serviceId": "d8f2092b-01de-424f-9068-32c4efdcfd45",
"driverId": "e1275ef6-f885-4724-9255-2e03868df5ee",
"eventList": [
{
"eventTime": "2019-07-18T13:09:01",
"eventId": 15,
"lat": 50.4130166,
"lon": -5.0739198
},
{
"eventTime": "2019-07-18T13:10:04",
"eventId": 21,
"lat": 50.412991299999995,
"lon": -5.073924
},
{
"eventTime": "2019-07-18T13:11:04",
"eventId": 21,
"lat": 50.413074599999995,
"lon": -5.074010299999999
},
{
"eventTime": "2019-07-18T13:12:04",
"eventId": 21,
"lat": 50.4131295,
"lon": -5.0739676
},
{
"eventTime": "2019-07-18T13:13:04",
"eventId": 21,
"lat": 50.4133475,
"lon": -5.073917499999999
},
{
"eventTime": "2019-07-18T13:14:04",
"eventId": 21,
"lat": 50.4133618,
"lon": -5.0739218
},
{
"eventTime": "2019-07-18T13:15:04",
"eventId": 21,
"lat": 50.4133333,
"lon": -5.073961
},
{
"eventTime": "2019-07-18T13:16:04",
"eventId": 21,
"lat": 50.4132803,
"lon": -5.0739765
},
{
"eventTime": "2019-07-18T13:17:04",
"eventId": 21,
"lat": 50.4133433,
"lon": -5.0739588
},
{
"eventTime": "2019-07-18T13:18:04",
"eventId": 21,
"lat": 50.413306999999996,
"lon": -5.0739355999999995
},
{
"eventTime": "2019-07-18T13:19:04",
"eventId": 21,
"lat": 50.4133013,
"lon": -5.073953599999999
},
{
"eventTime": "2019-07-18T13:20:04",
"eventId": 21,
"lat": 50.413309299999995,
"lon": -5.073988099999999
},
{
"eventTime": "2019-07-18T13:21:04",
"eventId": 21,
"lat": 50.4133146,
"lon": -5.0739618
},
{
"eventTime": "2019-07-18T13:22:04",
"eventId": 21,
"lat": 50.413287999999994,
"lon": -5.0739141
},
{
"eventTime": "2019-07-18T13:23:04",
"eventId": 21,
"lat": 50.4132981,
"lon": -5.0739008
},
{
"eventTime": "2019-07-18T13:24:04",
"eventId": 21,
"lat": 50.413283,
"lon": -5.07386
},
{
"eventTime": "2019-07-18T13:25:03",
"eventId": 52,
"lat": 50.413303,
"lon": -5.0738673
},
{
"eventTime": "2019-07-18T13:26:01",
"eventId": 60,
"lat": 50.4135111,
"lon": -5.0737745
},
{
"eventTime": "2019-07-18T13:27:02",
"eventId": 130,
"lat": 50.415140099999995,
"lon": -5.073355299999999
},
{
"eventTime": "2019-07-18T13:28:00",
"eventId": 125,
"lat": 50.4139743,
"lon": -5.0697981
},
{
"eventTime": "2019-07-18T13:29:01",
"eventId": 21,
"lat": 50.4186421,
"lon": -5.0698473
},
{
"eventTime": "2019-07-18T13:30:09",
"eventId": 153,
"lat": 50.418105999999995,
"lon": -5.0624391
},
{
"eventTime": "2019-07-18T13:30:50",
"eventId": 21,
"lat": 50.4185011,
"lon": -5.0581641
},
{
"eventTime": "2019-07-18T13:31:59",
"eventId": 21,
"lat": 50.417915099999995,
"lon": -5.0517363
},
{
"eventTime": "2019-07-18T13:33:02",
"eventId": 131,
"lat": 50.4194111,
"lon": -5.0496058
},
{
"eventTime": "2019-07-18T13:35:34",
"eventId": 51,
"lat": 50.4194153,
"lon": -5.049543
}
]
}
Как вы можете видеть (ближе к нижней части), у нас есть два раза в течение 13:30 {2019-07-18T13: 30: 50, 2019-07-18T13: 30: 09}
Технически я играюя хочу выбрать 2019-07-18T13: 30: 09 как ближайший к минуте (9 секунд, а другой - 10 секунд)
Кроме того, если вы посмотрите в ответ,времена имеют секунды и не округляются в меньшую сторону.
Пожалуйста, не стесняйтесь задавать любые дополнительные вопросы, если это не было ясно.