2

I need to display a list of account objects and sorting on one of the account object fields (all string type). However, some account fields value is null so NOT showing in the JSON. It gives me a null pointer exception when sorting on those missing field. How can I have the Comparator ignore the missing field during sorting ?

I tried Comparator.comparing() but it only works on the common field (existing in all account object). If I tried to sort on the field missing in one of the account objects. NullPointerException happens. Of course, if I tried to force all fields show up with those field as empty string value ("") then it works as normal but it does not look good since it might be too many of those fields.

Accounts definition

@JsonInclude(Include.NON_NULL)
private String type;    
@JsonInclude(Include.NON_NULL)
private String accountNumber;
@JsonInclude(Include.NON_NULL)
private String accountStatus;
@JsonInclude(Include.NON_NULL)
private String accountValue;
    .... 

Sort following list - only type and accountNumber are common

"accounts": [
 {
  "type": "type1",
  "accountNumber": "1816227",
  "accountStatus": "cancelled",
 },
 {
  "type": "type2",
  "accountNumber": "2816218",
  "accountValue": "19438.60",

 },
 {
  "type": "type3",
  "accountNumber": "2209890",
  "accountStatus": "inactive",
  "accountValue": "4343.410",
 }

  if (sortField.equalsIgnoreCase("type")) {         
   accountComparator = Comparator.comparing(Accounts::getType);
  }else if(sortField.equalsIgnoreCase("accountNumber")) {
   accountComparator = Comparator.comparing(Accounts::getAccountNumber);
  }else if(sortField.equalsIgnoreCase("accountStatus")) {
   accountComparator = Comparator.comparing(Accounts::getAccountStatus);
  }else if(sortField.equalsIgnoreCase("accountValue")) {    
  accountComparator = Comparator.comparingDouble(acc -> 
    Double.valueOf(acc.getAccountValue()));
   }
   ......  

Nullpointer exception on following line when Sort on accountStatus and accountValue which are missing in one of the accounts. totalAcctList.sort(accountComparator.reversed());

As mentioned, if I make all accounts showing accountStatus and accountValue such as "accountStatus":"" and "accountValue":"0.0" then it works.

1 Answer 1

5

You could decide to have all the nulls at the beginning or the end of the list, and use Comparator.nullsFirst or Comparator.nullsLast respectively:

else if (sortField.equalsIgnoreCase("accountStatus")) {
   accountComparator = 
       Comparator.comparing(Accounts::getAccountStatus, 
                            Comparator.nullsLast(Comparator.naturalOrder()));
}

EDIT:

For accountValue you could take a similar approach, although since primitive doubles can not be null, you'll have to handle them first, before attempting to parse:

else if (sortField.equalsIgnoreCase("accountValue")) {    
  accountComparator = 
      Comparator.comparing((Account a) -> a.getAccountValue() == null)
                .thenComparingDouble((Account a) -> 
                                     Double.parseDouble(a.getAccountValue()));
}
Sign up to request clarification or add additional context in comments.

6 Comments

Mureinik, thanks for the great comments. However, it appears that the Comparator.comparingDouble() for sorting on accountValue only have one parameter in the signature.
@user1747980 for doubles, you'll need a slightly different (less elegant) technique. See my edited answer.
"primitive doubles can be null" - you need to fix this text
@SharonBenAsher yup, missed the all important "not" there. Thanks for noticing. Edited and fixed.
Thanks Mureinik and Sharon for further improvement of the answer. Mureinik, so a.getAccountValue() == null should be a.getAccountValue() != null , right ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.