问题
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.
回答1:
There are two types of null
s you can have in your list. You can have null
Person
references, and you can have Person
s 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
Person
s get sorted properly, can be applied to the entire chain:
comparator = Comparator.nullsFirst(
Comparator.comparing(
Person::getName,
Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)
).thenComparing(...)
);
来源:https://stackoverflow.com/questions/46610076/attempting-to-use-comparator-to-sort-by-name-ignore-case-as-well-as-nulls-firs