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)));
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?
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()))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With