Java:将比较器重写为Lambda - nullsafe

时间:2017-03-15 10:33:56

标签: java lambda comparison

我怎样才能重写:

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);
  }
};

进入lambda?

根据this post,我试过这个:

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

然而,它失败了:

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)

编辑:即使我在比较之前检查比较对象为null,lambda也会失败:

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

...

for (Domain domain : domains) {
  if (domain == null) { // check here
    continue;
  }
  topByRank.add(domain); // here it fails
}

2 个答案:

答案 0 :(得分:2)

应该是:

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

因此我们根据domainRank对列表进行排序。但是我们要对Domain值为空的domainRank个对象做些什么呢?我们将把它们放在我们收藏的头上: Comparator.nullsFirst(Comparator.naturalOrder())

答案 1 :(得分:1)

您的代码将首先放置Domain个空值。如果要检查null rank ,则需要使用:

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

但请记住,如果等级不能小于0,这仅相当于原始比较器。否则,您将必须测试类似的表达式:

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

或者,您可能打算在原始代码中使用Float.MIN_VALUE而不是0。