Search code examples
javasortingnullpointerexceptionnested-properties

Collections.sort() on nested property values


I am working on sorting feature for a data table. I have JSF Web Controller:

@Named
@ViewScoped
public class SearchPlayerController implements Serializable {

    private List<Player> playerList;

    @EJB
    PlayerFacade playerFacade;

    @PostConstruct
    public void init() {
        if (playerList == null) {
            playerList = playerFacade.findAll();
        }
    }

    // getters and setters
    *
    *
    *
}

In this Controller I have a sorting method:

public String sortDataByClubName(final String dir) {
    Collections.sort(playerList, (Player a, Player b) -> {
        if(a.getClubId().getClubName()
            .equals(b.getClubId().getClubName())) {
            return 0;
        } else if(a.getClubId().getClubName() == null) {
            return -1;
        } else if(b.getClubId().getClubName() == null) {
            return 1;
        } else {
            if(dir.equals("asc")) {
                return a.getClubId().getClubName()
                    .compareTo(b.getClubId().getClubName());
            } else {
                return b.getClubId().getClubName()
                    .compareTo(a.getClubId().getClubName());
            }
        }
    });
    return null;
}

After invoking the sort on page view, it throws NullPointerException. I think the main reason is that inside the Comparator it can't read the value of clubName that should be accessible after getting Club object. Is there any possibility to compare values of nested properties?


Solution

  • You seem to be sorting only on Player.getClubId().getClubName(). It seems like both getClubId() and getClubName() should be checked for null. This is how I would do it:

    public class PlayerComparator implements Comparator<Player> {
        private String dir; // Populate with constructor
        public int compare(Player a, Player b) {
            int result = nullCheck(a.getClubId(), b.getClubId());
            if(result != 0) {
                return result;
            }
            String aname = a.getClubId().getClubName();
            String bname = b.getClubId().getClubName();
            result = nullCheck(aname, bname);
            if(result != 0) {
                return result;
            }
            result = aname.compareTo(bname);
            if("asc".equals(dir)) {   // No NPE thrown if `dir` is null
                result = -1 * result;
            }
            return result;
        }
    
        private int nullCheck(Object a, Object b) {
            if(a == null) { return -1; }
            if(b == null) { return 1; }
            return 0;
        }
    }