How do I deal with null and duplicate values in a Java 8 Comparator?

java 8 sort list with null values
comparator comparing null pointer exception
java 8 comparator multiple fields
java comparator null safe
integer comparator java
override comparator java
static comparator java
comparator.comparing reverse

I have a Photo object:

public class Photo {
    @Id
    private String id;
    private LocalDateTime created;
    private Integer poNumber;
}

poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set. If poNumber is duplicated then sort according to created (earliest created photo appears first). If poNumber is null then sort according to created.

I tried the below code:

Set<Photo> orderedPhotos = new TreeSet<>(
    Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
              .thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
    orderedPhotos.add(photo);
}

But it throws a NullPointerException whenever poNumber is null. If poNumber is not null then it works fine. How can I solve this issue?


You can use a two-argument Comparator.comparing overload, for example:

import static java.util.Comparator.*; // for the sake of brevity

Set<Photo> orderedPhotos = new TreeSet<>(
    Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
              .thenComparing(Photo::getCreated));

Compare two objects in Java with possible null values, return the result of calling equals on the first object with the second as argument. I have Photo object:poNumber can be null for some photos or all photos in a set. I want to sort set of photos according to poNumber, so that lowest poNumber appears first in the sorted set. poNumber may also be duplicate in the set. If poNumber is duplicate then sort according to created (earliest created photo appears first).


We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.

And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:

Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))

And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.

compare an object to null!, How do I sort a Map by value in Java 8? I have a Photo object:poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set.


The way you have written it, the Photo key could be null but nothing else.

Comparator.nullsFirst( // Photo could be null.
    Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
              .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null

If any of these can't be null you can remove the Comparator.nullsFirst

How to sort an array of objects containing null elements in java?, Return value: This method returns a comparator that considers null to be greater than non-null and compares non-null objects with the supplied Comparator. Java 8 stream distinct by multiple fields example. Learn to find distinct objects from a stream by comparing multiple fields or creating a custom key class.


This will put null values at the beginning

Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };

This will put null values at the end

Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };

Otherwise, implement your own comparator to handle the null values

Comparator nullsLast() method in Java with examples , A Map allows for at most one null value as its key and multiple null values as its values for view operations • Methods for comparison operations • The methods in the Since a Map may contain duplicate values, you get a Collection view of its values Entry<K, V>>entrySet() The comparison operations methods deal with  In this tutorials, I am going to show you how to remove duplicate elements from the list using Java 8 syntax. How to remove duplicates from list : Here I am creating a Department class, it holds department details. Department.java


Beginning Java 8 Language Features: Lambda Expressions, Inner , Only because our value is a simple int is it ascending in this case. into any hashed implementations results in duplicate values, so the primary contract of the Comparator comparator(): Produces the Comparator used for this Set, or null for  Returns a null-friendly comparator that considers null to be greater than non-null. When both are null, they are considered equal. If both are non-null, the specified Comparator is used to determine the order. If the specified comparator is null, then the returned comparator considers all non-null values to be equal.


On Java 8, Java 8 lambdas can be leveraged effectively with the Comparator interface as well. Let's randomly insert null values in employees array: ? Java 8 introduced several enhancements to the Comparator interface, including a handful of static functions that are of great utility when coming up with a sort order for collections. Java 8 lambdas can be leveraged effectively with the Comparator interface as well.


Guide to Java 8 Comparator.comparing(), Advanced Features (Core Series) Updated To Java 8. Harry. H. Chaudhary., Java Guru. 22. class MyComp implements Comparator 24. public int compare(​Object a, Object b) 25. The keys must be unique, but the value may be duplicated. Some maps can accept a null key and null values, other cannot Map Interfaces:  The important points about Java TreeMap class are: It stores key-value pairs similar to like HashMap. It allows only distinct keys. Duplicate keys are not possible. It cannot have null key but can have multiple null values. It stores the keys in sorted order (natural order) or by a Comparator provided at map creation time.