Sorting string value in a case-insensitive manner in Java 8
Asked Answered
P

7

54

How do I sort string values in case-insensitive order in the following?

List<Employee> listofEmployees = Arrays.asList(
    new Employee(1, "aaa", Arrays.asList(123, 345, 678)),
    new Employee(1, "bbb", Arrays.asList(91011, 121314, 1516117)),
    new Employee(2, "ccc", Arrays.asList(181920, 212223, 242526)),
    new Employee(3, "ddd", Arrays.asList(272829, 303132, 333435)),
    new Employee(4, "BBB", Arrays.asList(29, 332, 33))
);

I wrote like this:

listofEmployees.stream().sorted(Comparator.comparing(Employee::getName).reversed())
        .forEach(s -> System.out.println(s.getName()));

How do I pass a string case insensitive option here?

Permeate answered 13/4, 2018 at 16:50 Comment(0)
L
132

Try this

Comparator.comparing(Employee::getName, String.CASE_INSENSITIVE_ORDER)
Lucullus answered 13/4, 2018 at 16:54 Comment(4)
Beware: Note that this Comparator does not take locale into account, and will result in an unsatisfactory ordering for certain locales. The java.text package provides Collators to allow locale-sensitive ordering.Coalition
@TREE, How will you handle null-safe here?Krause
null handling appears to be implementation dependent in Collators. So the only safe way is to handle them outside the Collator.Coalition
Null handling is possible via Comparator.nullsFirst or nullsLast: Comparator.comparing(Employee::getName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER))Docile
F
30

As @Tree suggested in comments, one can use the java.text.Collator for a case-insensitive and locale-sensitive String comparison. The following shows how both case and accents could be ignored for US English:

Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.PRIMARY);
listOfEmployees.sort(Comparator.comparing(Employee::getName, collator.reversed()));

When collator strength is set to PRIMARY, then only PRIMARY differences are considered significant during comparison. Therefore, the following Strings are considered equivalent:

if (collator.compare("abc", "ABC") == 0) {
    System.out.println("Strings are equivalent");
}
Fiftieth answered 13/4, 2018 at 16:54 Comment(0)
G
18

You can specify it as the second argument to ignore cases:

Comparator.comparing(Employee::getName, String::compareToIgnoreCase).reversed()
Generate answered 13/4, 2018 at 16:56 Comment(3)
How will you handle null-safe here?Krause
Comparator.comparing(Employee::getName, Comparator.nullsFirst(String::compareToIgnoreCase)));Colossae
This should be the accepted answer.Consentaneous
O
4

This is one of many ways:

listofEmployees.stream()
    .sorted((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()))
    .forEach(s -> System.out.println(s.getName()));
Oneiromancy answered 13/4, 2018 at 16:55 Comment(0)
M
1

It looks like there is a Comparator that orders String objects as by compareToIgnoreCase, you can read the documentation here: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#CASE_INSENSITIVE_ORDER

Monreal answered 13/4, 2018 at 16:55 Comment(0)
F
0

Comparator.comparing(Employee::getName, String.CASE_INSENSITIVE_ORDER)

It worked for me

Fornix answered 11/1 at 5:36 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Voluptuous
A
-3

You can lowercase or uppercase it like this:

listofEmployees.stream()
               .sorted(Comparator.comparing((Employee e) -> e.getName()
                                 .toLowerCase()) // or toUpperCase
                                 .reversed())
               .forEach(s -> System.out.println(s.getName()));
Auroora answered 13/4, 2018 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.