Home > Mobile >  Sort elements based on their String property in case insensitive way
Sort elements based on their String property in case insensitive way

Time:09-22

The following code works but it does take into account upper or lower case, and the result is a non alphabetically ordered list:

List<Pair<IContributionItem, String>> itemsList = new ArrayList<>();

Comparator<Pair<IContributionItem, String>> filePathComparator = Comparator.comparing(Pair<IContributionItem, String>::getPathToFile);
        itemsList = itemsList.stream().sorted(filePathComparator).collect(Collectors.toList()); 

Then I came across String.CASE_INSENSITIVE_ORDER so I tried to add it to it:

Comparator<Pair<IContributionItem, String>> filePathComparator = Comparator.comparing(Pair<IContributionItem, String.CASE_INSENSITIVE_ORDER>::getPathToFile);
        itemsList = itemsList.stream().sorted(filePathComparator).collect(Collectors.toList()); 

But it gives an error: String.CASE_INSENSITIVE_ORDER cannot be resolved to a type.

What would be solution or workaround to accommodate the code?

CodePudding user response:

Problem

When we use Comparator.comparing(Function<? super T,? extends U> keyExtractor) the natural order of selected key/property is used while sorting. That order is defined by class of selected key when it implements Comparable<ClassOfElement>{..} or its ancestor does it.

Since your keyExtractor was extracting key of type String, the natural order defined in String class was applied, and that order is case-sensitive.

Solution

To build Comparator which will compare element based on its key/property, but at the same time use different order than natural one for that key, we can use overloaded version of previous method Comparator.comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator). Here the keyComparator allows us to pass different comparator for selected key.

Since you claimed that

Comparator.comparing(Pair<IContributionItem, String>::getPathToFile)

worked but in case-sensitive way, all you need to do is add String.CASE_INSENSITIVE_ORDER as second argument - the keyComparator

Comparator.comparing(Pair<IContributionItem, String>::getPathToFile, String.CASE_INSENSITIVE_ORDER)
                                                      // add this  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Extra

BTW you don't need to use angle brackets with method references since type inference should be able to figure out correct type based on context, so

Comparator.comparing(Pair::getPathToFile, String.CASE_INSENSITIVE_ORDER)

should also work fine.

  • Related