Amiko
Amiko

Reputation: 585

How to properly filter Lists using object's ID and LocalDateTime fields in Java?

Say we have following Dto Model.

public class OrderDto {
    Long id;
    LocalDateTime drawDate;
}

And we have following List which I need to filter and the result I need is also included.

List<OrderDto> orderDtoList = new ArrayList<>();

orderDtoList.add(new OrderDto(1L, LocalDateTime.now()));              // 1
orderDtoList.add(new OrderDto(1L, LocalDateTime.now().plusDays(1)));  // 2
orderDtoList.add(new OrderDto(1L, LocalDateTime.now().plusDays(2)));  // 3
orderDtoList.add(new OrderDto(2L, LocalDateTime.now().minusDays(1))); // 4
orderDtoList.add(new OrderDto(2L, LocalDateTime.now()));              // 5
orderDtoList.add(new OrderDto(2L, LocalDateTime.now().plusDays(1)));  // 6
orderDtoList.add(new OrderDto(2L, LocalDateTime.now().plusDays(2)));  // 7
orderDtoList.add(new OrderDto(3L, LocalDateTime.now().minusDays(2))); // 8
orderDtoList.add(new OrderDto(3L, LocalDateTime.now().minusDays(1))); // 9
orderDtoList.add(new OrderDto(3L, LocalDateTime.now()));              // 10

List<OrderDto> desiredList = new ArrayList<>();
desiredList.add(new OrderDto(1L, LocalDateTime.now().plusDays(1)));   // 2
desiredList.add(new OrderDto(2L, LocalDateTime.now().plusDays(1)));   // 6
desiredList.add(new OrderDto(3L, LocalDateTime.now()));               // 10

As you can see we have several OrderDto objects with the same ID, but I need to include in the desired list the ones which have drawDate more than LocalDateTime.now(). BUT only the first Object which is greater than LocalDateTime.now(). So obviously I need, the object with plusDays(1) not plusDays(2). Desired List can't have Objects with same ID in it.

ALSO Important thing. If the objects with the SAME ID don't have drawDate greater than LocalDatetime.now(). Then I will need to choose object with the latest drawDate. AS SHOWN in the desiredList

Another thing. Desired List can't have Objects with same ID in it. And there might be even 10 OrderDto objects with the same id, but chosen one will be the first one whose drawDate is greater than LocalDateTime.now()

I'm trying to come up with Java STREAM that will do it for me but having trouble with it. Any other solution is welcome.

Upvotes: 1

Views: 220

Answers (1)

Amiko
Amiko

Reputation: 585

Well I've come up with a method that does the job for me. If anyone out there can think of something better feel free to post it. I used sorting because list might not be sorted by drawDates, so I just to make sure I sort them before I extract any elements from it. It assures I get the right one. Then I reverse list in order to get first object with the nearest date to LocalDateTime.now().

 private List<OrderDto> getFilteredList(List<OrderDto> orderDtoList) {

    List<OrderDto> filteredList = new ArrayList<>();
    LocalDateTime now = LocalDateTime.now();

    List<OrderDto> sortedList = orderDtoList.stream().sorted(Comparator.comparing(OrderDto::getDrawDate)).collect(Collectors.toList());

    for (OrderDto dto : sortedList) {
        if (dto.getDrawDate().isAfter(now) && filteredList.stream().noneMatch(orderDto -> Objects.equals(orderDto.getId(), dto.getId()))) {
            filteredList.add(dto);
        }
    }

    Collections.reverse(sortedList);
    for (OrderDto dto : sortedList) {
        if (dto.getDrawDate().isBefore(now) && filteredList.stream().noneMatch(orderDto -> Objects.equals(orderDto.getId(), dto.getId()))) {
            filteredList.add(dto);
        }
    }

    return filteredList;
}

Upvotes: 1

Related Questions