当两者都为null时,使用Comparator.nullsFirst

时间:2017-05-24 07:56:02

标签: java java-8 comparator

我有一个包含多个“可选”(不是java.util.Optional)字段的类。我正在编写一个Lambda比较器,通过比较其属性的子集来测试相等性

我写了

private final static Comparator<MyEntity> COMPARATOR_491 =  
            comparing(MyEntity::getIsin)
             .thenComparing(MyEntity::getTMarketType)
             .thenComparing(nullsFirst(comparing(MyEntity::getIsoCode)))
             .thenComparing(MyEntity::getTaxRate)
             .thenComparing(nullsFirst(comparing(MyEntity::getEndDate)));
  • ISIN不为空
  • 市场类型不为空
  • 代码是否为空
  • 税率不为空
  • 结束日期可以为空

问题是我常常得到NullPointerException。这是(几乎不可读)堆栈跟踪

java.lang.NullPointerException: null
    at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) ~[?:1.8.0_51]
    at java.util.Comparator$$Lambda$40/221702765.compare(Unknown Source) ~[?:?]
    at java.util.Comparators$NullComparator.compare(Comparators.java:83) ~[?:1.8.0_51]
    at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:217) ~[?:1.8.0_51]
    at java.util.Comparator$$Lambda$42/770739971.compare(Unknown Source) ~[?:?]
    at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:216) ~[?:1.8.0_51]
    at java.util.Comparator$$Lambda$42/770739971.compare(Unknown Source) ~[?:?]
    at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:216) ~[?:1.8.0_51]
    at java.util.Comparator$$Lambda$42/770739971.compare(Unknown Source) ~[?:?]

我发现两个样本实体因结束日期而异。第一个实体具有非null属性,第二个实体具有null

我认为当一个或两个参数为空时,nullsFirst comparer可以为null安全。

我做错了什么?

1 个答案:

答案 0 :(得分:10)

nullsFirst(…)返回的比较器返回一个比较器,用于处理要比较的一个或两个对象为null的情况。

因此,当您说nullsFirst(comparing(MyEntity::getIsoCode))时,您会得到一个比较器,处理MyEntity个实例中的任何一个或两个null getIsoCode并根据其自然顺序比较null属性的情况(如果MyEntity实例均不是null,则不处理comparing(MyEntity::getIsoCode, nullsFirst(naturalOrder()))值。

您希望实现的目标是null,指定用于比较属性值的getEndDate安全比较器。这同样适用于thenComparing属性。

您可以将其与previousComparator.thenComparing(MyEntity::getIsoCode, nullsFirst(naturalOrder()))融合到let plus1 = d => d += 1; let plus2 = d => d += 2; let write = d => document.write(d); let execute = function(n,...functions){ functions.forEach((d)=>d(n)); } execute(4,plus1,plus2,write);