2

I already know that we can sort string arrays numerically, by converting them to integer array then using Arrays.sort() or using any comparator.

So my question is if those strings are beyond the limit of integer or long int then how can we sort them. For example consider the following string array:

14829435897932384626433832795
4159265358979323846264338327
1937286535897932384626433832795296523
23746289

in those cases traditional comparator or any sorting method won't work because in turn they use integer (or any other datatype).

6
  • 2
    Convert them to BigInteger Commented Nov 14, 2017 at 13:52
  • 5
    Option 1: BigInteger Option 2: compare by length first, if that is equal, compare as String Commented Nov 14, 2017 at 13:53
  • 2
    BigInteger seems a better option specifically for cases where the String can start with a bunch of zeros, e.g. 000133124953. Length comparison would be problematic here. Commented Nov 14, 2017 at 13:55
  • 1
    yes biginteger seems better . Thanks @Eran , @ GaborSch , @ Everyone Commented Nov 14, 2017 at 13:57
  • 1
    I would prefer option 2 (compare string length then compare as String) with a comparator that skips any leading zeros. It would probably be more efficient as you won't be creating new objects and allocating arrays to hold the BigInteger values. If readability is the only requirement, then use BigInteger. Commented Nov 14, 2017 at 14:02

3 Answers 3

9

As suggested by Eran: Convert to BigInteger and do the comparison:

Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        BigInteger bi1 = new BigInteger(o1);
        BigInteger bi2 = new BigInteger(o2);
        return bi1.compareTo(bi2);
    }
});

And because @tobias_k doesn't care about karma:

If you're running Java 8, you can use the many new default methods of the Comparator interface to do it in one line:

Arrays.sort(arr, Comparator.comparing(BigInteger::new))

Just added a counter to the Comparator to see how many times a String was converted to a BigInteger. It counted 10 conversions in my simple run of 4 strings.

This made me think that there might be a performance gain by converting each string once, sorting the BigInteger instances and converting them back. Something like this:

List<BigInteger> list1 = list.stream().map(BigInteger::new)
     .sorted().collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

3 Comments

Java 8: Arrays.sort(arr, Comparator.comparing(BigInteger::new))
@tobias_k: Nice! You should add that as answer.
Meh, it's basically the same. Feel free to add it to yours if you like.
8

You can use Arrays.sort(array, comparator)

Arrays.sort(array, Comparator.comparing(BigInteger::new));

With details (from shorter to longer, Intellij will propose you to use 1st one) : :

= Comparator.comparing(BigInteger::new)
= Comparator.comparing(val -> new BigInteger(val))
= Comparator.comparing((o1, o2) -> new BigInteger(o1).compareTo(new BigInteger(o2)))

String[] array = new String[]{"14829435897932384626433832795", 
                              "4159265358979323846264338327", 
                              "1937286535897932384626433832795296523", "23746289"};
Arrays.sort(array, Comparator.comparing(BigInteger::new));
System.out.println(Arrays.toString(array));

//Will result in 
[23746289, 4159265358979323846264338327, 14829435897932384626433832795, 1937286535897932384626433832795296523]

3 Comments

Its a great solution definately , but there are some efficiency issue with it .
@SandipKumar details ?^^ You have a lot of String to convert and sort ?
yep , the one which i have given are just sample ones , actual ones are way too larger .
3

You can also create a custom comparator:

List<String> list = Arrays.asList("14829435897932384626433832795", "4159265358979323846264338327", "1937286535897932384626433832795296523", "23746289", "4159265358979323846264338326");

// comparing by String if the length is equal
Collections.sort(list, Comparator.comparingInt(String::length).thenComparing(String::compareTo));

System.out.println(list);

Output:

[23746289, 4159265358979323846264338326, 4159265358979323846264338327, 14829435897932384626433832795, 1937286535897932384626433832795296523]

3 Comments

As noted above, it works only if there are no leading zeros. But it we can assume it, this is the most effective. +1
Arrays.sort(array, Comparator.comparingInt(String::length).thenComparing(String::compareTo));
This was the exact solution i was looking for , it is correct as well as efficient , thanks .

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.