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

usr*_*ΛΩΝ 6 java comparator java-8

我有一个有几个"可选"(非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)));
Run Code Online (Sandbox Code Playgroud)
  • ISIN不为空
  • 市场类型不为空
  • 代码可以为null
  • 税率不为空
  • 结束日期可以为空

问题是我常常得到一个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) ~[?:?]
Run Code Online (Sandbox Code Playgroud)

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

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

我究竟做错了什么?

Hol*_*ger 14

比较器通过返回nullsFirst(…)返回其处理,所述对象中的一个或两者进行比较是的情况下的比较器null.

因此,当你说nullsFirst(comparing(MyEntity::getIsoCode)),你得到一个比较器来处理一个或两个MyEntity实例的情况,nullgetIsoCode根据它们的自然顺序(不处理null值)比较属性,如果两个MyEntity实例都没有null.

您想要实现的是comparing(MyEntity::getIsoCode, nullsFirst(naturalOrder())),指定null用于比较属性值的-safe比较器.这同样适用于该getEndDate物业.

你可以把它融合thenComparingpreviousComparator.thenComparing(MyEntity::getIsoCode, nullsFirst(naturalOrder()))