Working of Comparator.nullsFirst when both are null

我们两清 提交于 2019-12-22 05:11:24

问题


I have a class with several "optional" (not java.util.Optional) fields. I was writing a Lambda comparator to test for equality by comparing a subset of their attributes

I wrote

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 is not null
  • Market type is not null
  • Is code can be null
  • Tax rate is not null
  • End date can be null

The problem is that often I get a NullPointerException. This is the (barely readable) stack trace

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) ~[?:?]

I found that two sample entities differ by the End date. The first entity has non-null property, the second has null

I thought that nullsFirst comparer could be null safe when one or both arguments are null.

What am I doing wrong?


回答1:


The comparator returned by nullsFirst(…) returns a comparator which handles the case that one or both of the objects to compare are null.

So when you say nullsFirst(comparing(MyEntity::getIsoCode)), you get a comparator handling the case that either or both MyEntity instances are null and comparing the getIsoCode property according to their natural order (not handling null values), if neither MyEntity instance is null.

What you want achieve, is comparing(MyEntity::getIsoCode, nullsFirst(naturalOrder())), specify the null-safe comparator to be used to compare the property values. The same applies to the getEndDate property.

You may fuse it with thenComparing, to previousComparator.thenComparing(MyEntity::getIsoCode, nullsFirst(naturalOrder()))



来源:https://stackoverflow.com/questions/44152312/working-of-comparator-nullsfirst-when-both-are-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!