Потоки Java 8 удаляют дубликаты записи, сохраняют которые имеют минимальную дату и возвращают обновленный список объектов

#java #list #stream #java-stream #grouping

Вопрос:

у меня есть java-боб, такой как

 class OrderDeatils {
    Long orderId;
    Long userId;
    OrderInfo info;

    \Required getter/setter
}

class OrderInfo {
    OffsetDateTime orderCreatedDate;
    
     \Required getter/setter
}
 

У меня есть данные в виде List<OrderDeatils> списка

 orderId.   userId.  OrderInfo[orderCreatedDate]. 
1001.       123.      2015/07/07 
1002.       124.      2015/08/07 
1003.       125.      2015/09/07 
1004.       123.      2015/08/07 

 

Как я могу удалить дублирующуюся запись на основе идентификатора пользователя и сохранить данные с минимальной датой, как показано ниже:

 orderId.   userId.  OrderInfo[orderCreatedDate]. 
1001.       123.      2015/07/07 
1002.       124.      2015/08/07 
1003.       125.      2015/09/07 
 

Должен возвращать список всего объекта OrderDeatils.

Я пытался, как:

  list.stream().collect(
                Collectors.groupingBy(OrderDeatils::getUserId,
                        Collectors.collectingAndThen(
                                Collectors.reducing((OrderDeatils d1, OrderDeatils d2)
                                        -> d1.getInfo.getOrderCreatedDate().isBefore(d2.getInfo.getOrderCreatedDate()) ? d1 : d2), Optional::get)));
 

Но ответ не такой, как ожидалось, я не обновляюсь List<OrderDeatils> по мере вывода.

Ответ №1:

Я не буду писать код для вас, но вот шаги:

  • вам нужен Collectors::toMap тот, который может выполнить «слияние» в третьем аргументе. Что-то вроде:
 ...collect(Collectors.toMap(
     OrderDeatils::getUserId,
     Function.identity(),
     (left, right) ->
        left.getInfo.getOrderCreatedDate().isBefore(right.getInfo.getOrderCreatedDate()) ? left : right        
))
 
  • Это даст вам Map<Long, OrderDeatils> то, от чего вам нужны только ценности.

Комментарии:

1. Спасибо, что сработало …небольшой вопрос по этому поводу, если OrderInfo является родительским классом для OrderDeatils …. как OrderDeatils расширяет OrderInfo.. мы получим тот же результат … извините за то, что задал вопрос, должен создать новую тему. Но если вы можете внести свой вклад.

2. @utpalsharma где твой вопрос?

3. Спасибо, я создам новый

Ответ №2:

Вы можете использовать простой набор для фильтрации. При добавлении в набор — метод .add() вернет true, если это новое значение, и false, если значение уже существует в наборе.

Для сортировки вы можете использовать .sorted() и передать компаратор для сортировки по нужному полю.

 Set<String> userIdsSet = new HashSet<>();
List<OrderDetails> filteredOrderDetails = list.stream()
            .filter(e -> userIdsSet.add(e.getUserId()))
            .sorted(Comparator.comparing(OrderDetails::getOrderCreatedDate()))
            .collect(Collectors.toList());
 

Комментарии:

1. Это нарушает рекомендацию о безгражданстве в поведенческих параметрах.