0

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 :)

7
  • you need to create a Comparator and pass it to the Collections.sort(list,comparator). Since, your sorting order is case sensitive, you shoudl not be using compareToIgnoreCase(o2) Commented Jun 28, 2018 at 5:21
  • I need help with the logic I have to use in Comparator. Commented Jun 28, 2018 at 5:24
  • What rule specifies the collation order? Is it AaBbCcDd... etc? You will need a custom comparator to accomplish this. Commented Jun 28, 2018 at 5:25
  • @JimGarrison sorting should be in alphabetical order. But when it comes to 'a,A' A should come first. I don't know what a collation order is. AaBbCcDd... I guess. Commented Jun 28, 2018 at 5:28
  • your aim is to sort based the Upper case Character in the String? Commented Jun 28, 2018 at 5:43

2 Answers 2

7

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())
Sign up to request clarification or add additional context in comments.

6 Comments

Minus: -s1.compareTo(s2) and then the answer is just what the OP wanted: b < B
Not from the output I see in the question @JoopEggen : "BUBBLE < buBble"
you are right - still did not have my morning coffee. BTW: nice occasion to offer comparing+andThen.
I wasn't aware of that feature @JoopEggen but this is added and this is indeed really nice.
I tried @JoopEggen but the method comparing(Function, Comparator) used is overloaded only with comparing(Function). So I can't make this work with comparing(String::compareToIgnoreCase). But I can remove the second comparator since this is the defaut comparator for String and have .thenComparing(Function.identity())
|
2
    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;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.