简体   繁体   中英

comparator with one to many relation filed

i have a DTO object ClientInfo that holds a List of document entity.

i use the following compare method to sort clientInfo list by documentCreationDate DESC.

    @Override
        public int compareTo(ClientInfo o) {

            Date firstmaxDate = this.getDocuments().stream().map(d -> d.getCreateDate()).max(Date::compareTo).get();
            Date secondmaxDate = o.getDocuments().stream().map(d -> d.getCreateDate()).max(Date::compareTo).get();
            return firstmaxDate.compareTo(secondmaxDate);

        }
List<ClientInfo> clientInfos= serverReturnedList......;
Collections.sort(clientInfos);

But its getting an exception telling that comparison rule has been violated. so im not getting the expected result. can anyone explain whats the way to achieve this.

This is the exception stack trace

java.util.NoSuchElementException: No value present
        at java.util.Optional.get(Optional.java:135)
        at com.orsbv.hcs.dto.ClientInfo.compareTo(ClientInfo.java:346)
        at com.orsbv.hcs.dto.ClientInfo.compareTo(ClientInfo.java:24)
        at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
        at java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
        at java.util.Arrays.sort(Arrays.java:1312)
        at java.util.Arrays.sort(Arrays.java:1506)
        at java.util.ArrayList.sort(ArrayList.java:1462)
        at java.util.Collections.sort(Collections.java:141)

You should keep your compareTo() method as it's written, because it's sorting according to natural ordering (ascending), which makes sense.

Instead you should change the sort, to tell it to sort in reverse (descending) order.

List<ClientInfo> clientInfoList = ...
Collections.sort(clientInfoList, Comparator.reverseOrder());

UPDATE based on info added to question:

Some of your ClientInfo don't have any documents that you can use to check created date.

When you do this:

 Date firstmaxDate = this.getDocuments().stream().map(d -> d.getCreateDate()).max(Date::compareTo)

the max() returns an Optional<Date> which allows it to return Optional.empty() in the case of an empty stream. When you've a ClientInfo without any document, you're calling get() on an empty Optional , which causes this exception.

You need to determine whether this case can occur in the real data, and if so, how you want to sort ClientInfo with no document. If all your createdDates are in the past, you could simply replace "no created date" with "now":

        Date thisDate = this.getDocuments()
                .stream()
                .map(Document::getCreateDate)
                .max(Date::compareTo)
                .orElseGet(Date::new);
        Date otherDate = o.getDocuments()
                .stream()
                .map(Document::getCreateDate)
                .max(Date::compareTo)
                .orElseGet(Date::new);

Or, you could stop before get() , work with Optional<Date> and check for isPresent() and handle as needed.

firstly i added a maxDocuemntCreationDate field to clientInfo.

  Date maxCreationDate = clientInfo.getDocuments()
                        .stream()
                        .map(Document :: getCreateDate)
                        .max(Date::compareTo)
                        .orElseGet(Date::new);

Then i compare in this fashion

 @Override
            public int compareTo(ClientInfo o) {


              return 
              this.getMaxCreationDate().compareTo(o.getMaxCreationDate());

            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM