arranging elements in a list in ascending order (first the percentages in increasing manner followed by alphabets case insensitively)

Viewed 61

I have a list of objects

List<Label> toReturn = new ArrayList<Label>();
toReturn.add(new Label("hbc"));
toReturn.add(new Label("Abc"));
toReturn.add(new Label("dbc"));
toReturn.add(new Label("0%"));
toReturn.add(new Label("10%"));
toReturn.add(new Label("20%"));
toReturn.add(new Label("40%"));
toReturn.add(new Label("100%"));

Label pojo has string property label . I want to sort the list alphabetically. Percentages should appear first in increasing manner followed by alphabets in case insensitive manner

I have used the snippet

toReturn.sort(Comparator.comparing(Label::getLabel, String.CASE_INSENSITIVE_ORDER));

which sorts the list with elements having property label in order "0%","10%","100%","20%","40%","Abc","dbc","hbc"

But I want in the order "0%","10%","20%","40%","100%","Abc","dbc","hbc"

How do I solve this ?

1 Answers

The comparator you're using is applying lexicographical ordering (where 1 comes before 2, and so on). It is not aware of any numeric patterns. It's easy to write a custom comparator that matches against a regular expression:

private static final Pattern PATTERN = Pattern.compile("(\\d+)%");

...

toReturn.sort((l1, l2) -> {
        var matcher1 = PATTERN.matcher(l1.label);
        var matcher2 = PATTERN.matcher(l2.label);
        if (matcher1.matches() && matcher2.matches()) {
            int value1 = Integer.parseInt(matcher1.group(1));
            int value2 = Integer.parseInt(matcher2.group(1));
            return Integer.compare(value1, value2);
        }
        return l1.label.compareToIgnoreCase(l2.label);
});
Related