Augustine Samuel
Augustine Samuel

Reputation: 29

Sorting Arraylist in a custom order

Thank you for lending your time :)

I have a piece of code that sorts Arraylist using compareToIgnoreCase.

Collections.sort(als,new Comparator<String>() {

        @Override
        public int compare(String o1, String o2) {
            //I want to alter this part
            int dif=o1.compareToIgnoreCase(o2); 
            return dif;
        }


    });

But I want to sort the arraylist in the following manner:

input: (in any order)

sherin
Sherin
SHERIN
bubBle
buBble
BUBBLE
heart
hEart
hEArt

output :

BUBBLE
buBble
bubBle
hEArt
hEart
heart
SHERIN
Sherin
sherin

Could you please help me with this? Thanks in advance :)

Upvotes: 0

Views: 96

Answers (2)

Alexander
Alexander

Reputation: 61

    public int compare(String s1, String s2) {
        int n1 = s1.length();
        int n2 = s2.length();
        int min = Math.min(n1, n2);
        for (int i = 0; i < min; i++) {
            char c1 = s1.charAt(i);
            char c2 = s2.charAt(i);
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);
            char l1 = Character.toLowerCase(c1);
            char l2 = Character.toLowerCase(c2);

            if (u1 != u2) {
                return u1 - u2;
            } else {
                if (l1 != l2) {
                    return l1 - l2;
                } else if (c1 != c2) {
                    return c1 - c2;
                }
            }
        }
        return n1 - n2;
    }

Upvotes: 2

AxelH
AxelH

Reputation: 14572

Your first try wasn't too bad, but you need to add another comparison in case of similar case insensitive values to order them :

Stream.of("sherin", "Sherin", "SHERIN", "bubBle", "buBble", "BUBBLE", "heart", "hEart", "hEArt")
    .sorted((s1, s2) -> {
        int tmp = s1.compareToIgnoreCase(s2); 
        return tmp == 0 ? 
            s1.compareTo(s2) //Compare equivalent values based on the case (upper case first)
            : tmp;
    }).forEach(System.out::println);

The comparator provided to Stream.sorted is the same has your implementation but using a lambda notation.

Result :

BUBBLE
buBble
bubBle
hEArt
hEart
heart
SHERIN
Sherin
sherin

EDIT: Thanks to Joop Eggen for the suggestion of using the comparator decorator :

Comparator
    .comparing(Function.identity(), String::compareToIgnoreCase)
    .thenComparing(Function.identity(), String::compareTo);

This is a bit cleaner to use and give the same result :

Stream.of("sherin", "Sherin", "SHERIN", "bubBle", "buBble", "BUBBLE", "heart", "hEart", "hEArt").sorted(
        Comparator
            .comparing(Function.identity(), String::compareToIgnoreCase)
            .thenComparing(Function.identity(), String::compareTo)
    ).forEach(System.out::println);

And the shorter I could do with this notation is :

Comparator.comparing((String s) ->.toLowerCase()).thenComparing(Function.identity())

Upvotes: 7

Related Questions