Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attempting to use Comparator to sort by name, ignore case, as well as nulls first

I am having issues using the Java 8 Comparator class to sort a list of items.

My current working comparator is below:

comparator = Comparator.comparing(Person::getName, Comparator.nullsFirst(Comparator.naturalOrder()));

This works: it orders the list by name with the null values first. However, I am now attempting to ignore case of the names.

I know that I can write a new getter that returns the name all lowercase, but I do not want to go with this approach as I have to do this for multiple attributes.

Looking online, it looks like I should be using String.CASE_INSENSITIVE_ORDER, but the only examples I see do not include the null ordering specification.

I can do something like this:

comparator = Comparator.comparing(Person::getName, String.CASE_INSENSITIVE_ORDER);

However, whenever I try to include the Comparator.nullsFirst I end up getting type errors, and am confused on how to continue.

I've tried doing a chain similar to

thenComparing(Comparator.nullsFirst(Comparator.naturalOrder))

but that also doesn't work.

Could someone lend me some advice on how I can chain these together to sort by name (not case sensitive) and then order the nulls. I seem to be confusing myself with the types.

like image 272
Aweava Avatar asked Oct 06 '17 16:10

Aweava


People also ask

How do you use comparators to sort an array?

Comparators are used to compare two objects. In this challenge, you'll create a comparator and use it to sort an array. The Player class is provided in the editor below. It has two fields: : a string. : an integer. Given an array of Player objects, write a comparator that sorts them in order of decreasing score.

What is the difference between nullsfirst and comparator?

Like the nullsFirst method, when both the arguments are null, they are considered as equal. If both are non-null, it uses the specified comparator to determine the order. If the specified comparator is null, then it considers all non-null values to be equal.

When would you use a comparator?

There are many possible places where we would use a Comparator. We might use it for sorting a list or an array, pass a Comparator to a TreeSet or a TreeMap, or sort a stream of objects using a Comparator. When there are one or more null elements in the collection, we would get a NullPointerException.

How do you reverse the Order of a comparator?

Using Comparator.reversed When invoked on an existing Comparator, the instance method Comparator.reversed returns a new Comparator that reverses the sort order of the original. Let's use the Comparator that sorts the employees by name and reverse it so that employees are sorted in descending order of the name:


1 Answers

There are two types of nulls you can have in your list. You can have null Person references, and you can have Persons with null names.

In the first case, you have to apply nullsFirst to the base comparator you want to use:

comparator = Comparator.nullsFirst(
        Comparator.comparing(Person::getName, String.CASE_INSENSITIVE_ORDER));

If you have the possibility of null names, you need to make sure that your key never returns a null, or that you apply nullsFirst to String.CASE_INSENSITIVE_ORDER. The second option is of course much easier:

comparator = Comparator.comparing(
        Person::getName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER));

If you have both options (null references and null names), you will have to combine both versions and apply nullsFirst twice:

comparator = Comparator.nullsFirst(
        Comparator.comparing(
                Person::getName,
                Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)
        )
);

If you are chaining multiple comparisons like this, the outer nullsFirst, which ensures that null Persons get sorted properly, can be applied to the entire chain:

comparator = Comparator.nullsFirst(
        Comparator.comparing(
                Person::getName,
                Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)
        ).thenComparing(...)
);
like image 157
Mad Physicist Avatar answered Oct 13 '22 20:10

Mad Physicist