0

I have a String array where there is a white space in the middle. I want to sort the contents based on the first substring before the white space, and then the substring after the white space.

For example, if my array looks like this: {"Henry 123", "Henry 234", "David 123", "David 234"}, in the end I want {"David 123", "David 234", "Henry 123", "Henry 234"}.

I tried implement a new comparator below:

import java.util.*;

public class MyClass {
    public static void main(String args[]) {
        String[] str_arr = {"Henry 123", "Henry 234", "David 123", "David 234"};

        Collections.sort(str_arr, new Comparator<String>(){
            
            public int compare(String s1, String s2) {
                String[] str1 = s1.split(" ");
                String[] str2 = s2.split(" ");
                if(str1[0].compareTo(str2[0]) != 0) {
                    return str1[0].compareTo(str2[0]);
                }
                return str1[1].compareTo(str2[1]); 
            }            
        });
        
        for (int i = 0; i < str_arr.length; i++) {
            System.out.printf("%s, ", str_arr[i]);
        }
    }
}

But I am getting this error:

MyClass.java:7: error: no suitable method found for sort(String[],<anonymous Comparator>) Collections.sort(str_arr, new Comparator(){ ^ method Collections.<T#1>sort(List<T#1>) is not applicable (cannot infer type-variable(s) T#1 (actual and formal argument lists differ in length)) method Collections.<T#2>sort(List<T#2>,Comparator<? super T#2>) is not applicable (cannot infer type-variable(s) T#2 (argument mismatch; String[] cannot be converted to List<T#2>)) where T#1,T#2 are type-variables: T#1 extends Comparable<? super T#1> declared in method <T#1>sort(List<T#1>) T#2 extends Object declared in method <T#2>sort(List<T#2>,Comparator<? super T#2>) 1 error

This error sounds like Collections framework does not support sorting strings, which does not make much sense.

3
  • What order would you want { "Henry 123", "Henry 23", "David 53", "David 234" } to be sorted? Please show expected result. Commented Jan 22, 2022 at 19:26
  • Maybe I am missing something, but splitting the string seems unnecessary. You are comparing first string and if they are the same you compare the second, but just comparing the entire string will give exactly the same result... Commented Jan 22, 2022 at 20:26
  • @magicmn True, I was initially thinking comparing strings of digits and digits will yield the same result, but as WJS pointed out, it was not the case. Commented Jan 22, 2022 at 20:50

2 Answers 2

3

Here is one way.

String[] arr = { "Henry 123", "Henry 234", "David 123",
        "David 234" };

Comparator<String> comp =
        Comparator.comparing(s -> s.split("\\s+"),
                Comparator.comparing((String[] a) -> a[0])
                        .thenComparing(a -> a[1]));

Arrays.sort(arr,comp);
System.out.println(Arrays.toString(arr))

prints

[David 123, David 234, Henry 123, Henry 234]

If you want to compare the second value as an int then change to.

...thenComparingInt(a -> Integer.parseInt(a[1])));

Remember that comparing numbers as strings is lexical not numerical so the results can vary. For example, comparing [55, 123] as strings would result in [123, 55] since 55 is lexically greater than 123. And the reason your solution didn't work is that arrays are not collections which is what Collections.sort() expects.

Sign up to request clarification or add additional context in comments.

Comments

3

You have a String array, which the Collection.sort method indeed does not support sorting. Collections.sort is for sorting Lists.

You should use Arrays.sort instead:

Arrays.sort(str_arr, (s1, s2) -> {
    String[] str1 = s1.split(" ");
    String[] str2 = s2.split(" ");
    int firstPartcomparison = str1[0].compareTo(str2[0]);
    if(firstPartcomparison != 0) {
        return firstPartcomparison;
    }
    return str1[1].compareTo(str2[1]);
});

2 Comments

This is also super helpful, but the other answer gave a more in-depth explanation and alerted a pitfall. Unfortunately I can only accept one answer :(
@kd8 Oh right. I didn't notice that! I probably would have noticed if some of the numbers have different numbers of digits :)

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.