How to Sort List based on Inner Object’s property in java 8



I have classes structure similar to:

    class FinalResponse {
        Source source;
        List<Target> targets;
    }
    
    class Response {
    Source source;
    Target target;
   }

    class Source {
        Long sourceId;
        String sourceName;
    }
    
    class Target {
        Long targetId;
        String targetName;
    }

I have two different tables Source and Target, and after joining them I am getting four columns in the query output. I am constructing Response object using values of these four columns. I have data in Response object with these 4 properties sourceId, sourceName, targetId, targetName. I can have sourceId, sourceName same on the multiple rows but targetId, targetName will always be different.

I grouped all the target objects into the List for which source is the same.

List<FinalResponse> finalResponses = responses.stream()
    .collect(Collectors.groupingBy(
        Response::getSource,
        LinkedHashmap::new,
        Collectors.mapping(Response::getTarget, Collectors.toList())
    )) // Map<Source, List<Target>> is built
    .entrySet()
    .stream() // Stream<Map.Entry<Source, List<Target>>>
    .map(e -> new FinalResponse(e.getKey(), e.getValue()))
    .collect(Collectors.toList());

But sometimes reponse from database cannot be sorted and even though it is sorted and I have used LinkedHashmap::new then also my final output List<FinalResponse> finalResponses is not sorted. I wanted my final output to be sorted as per sourceId, so I did:

finalResponses.sort(Comparator.comparing(finalResponse->finalResponse.getSource().getSourceId()));

It is working fine for non null values but if I have source(sourceId=null,sourceName=null) on multiple rows then I am getting NullPointerException. What is the best approach to Sort Collection based on Source Object’s sourceId property ?

Answer

Comparator.nullsLast or Comparator.nullsFirst should be applied to handle possible null values in the compared items:

finalResponses.sort(Comparator.nullsLast(
    Comparator.comparing(fr -> fr.getSource().getSourceId())
));

or like this:

finalResponses.sort(Comparator.comparing(
    fr -> fr.getSource().getSourceId(),
    Comparator.nullsLast(Comparator.naturalOrder())
));


Source: stackoverflow