1

How can i rewrite this:

private Comparator<Domain> byRank;

...

byRank = new Comparator<Domain>() {
  @Override
  public int compare(Domain d1, Domain d2) {
    float tmp1 = d1.getDomainRank() == null ? 0 : d1.getDomainRank();
    float tmp2 = d2.getDomainRank() == null ? 0 : d2.getDomainRank();
    return Float.compare(tmp1, tmp2);
  }
};

into lambda?

According to check null value before sorting using lambda expression, I tried this:

byRank = Comparator.nullsFirst(Comparator.comparing(Domain::getDomainRank));

However, it fails with:

java.lang.NullPointerException: null
    at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
    at java.util.Comparators$NullComparator.compare(Comparators.java:83)
    at java.util.PriorityQueue.siftUpUsingComparator(PriorityQueue.java:669)
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:645)
    at java.util.PriorityQueue.offer(PriorityQueue.java:344)
    at java.util.PriorityQueue.add(PriorityQueue.java:321)

Edit: the lambda fails even if I check compared objects for null before comparison:

Queue<Domain> topByRank = new PriorityQueue<>(TOP, byRank);

...

for (Domain domain : domains) {
  if (domain == null) { // check here
    continue;
  }
  topByRank.add(domain); // here it fails
}
3
  • For what I see d1 or d2 should be null Commented Mar 15, 2017 at 10:36
  • @freedev I check for null object (see edit). And the non-lambda version works without failing. Wouldn't it fail on d1.getDomainRank() or d2.getDomainRank() too? Commented Mar 15, 2017 at 10:45
  • Comparator.comparing is throwing the NPE. You have to turn the calls around. See stackoverflow.com/a/28500970/982149 Commented Mar 15, 2017 at 10:46

2 Answers 2

5

It should be:

Comparator.comparing(Domain::getDomainRank,
           Comparator.nullsFirst(Comparator.naturalOrder()))

So we sort a list based on domainRank. But what are we going to do with Domain objects whose domainRank value is null? We going to keep them at the head of our collection: Comparator.nullsFirst(Comparator.naturalOrder())

Sign up to request clarification or add additional context in comments.

Comments

2

Your code will put null Domains first. If you want to check for null rank, you need to use this:

Comparator.comparing(Domain::getDomainRank, Comparator.nullsFirst(Comparator.naturalOrder()))

But keep in mind that this is only equivalent to your original comparator if the rank can't be less than 0. Otherwise, you'll have to test a similar expression:

Comparator.comparing(d -> d.getDomainRank() == null ? 0 : d.getDomainRank())

Alternatively, you might have meant to use Float.MIN_VALUE instead of 0 in your original code.

1 Comment

Thats it, and thank you for that warning about zero boundary.

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.