1

I want to sort a list of String that also contains numbers.

For example, I have a list containing elements "1,2,3,4,5,11,12,21,22,31,32,A101,A102,A103,A104,B405".

If i use Collection.sort method means output is "1,11,12,2,21,22,3,31,32... ".

If i use Comparator function means it gives output as "1,2,3,4,5,11,12,21,22,31,32,A101... ".

But i need to display as

"A101,A102,A103,A104,B405,1,2,3,4,5,11,12,21,22,31,32"

Please any one give me a solution. Thanks in advance.

1
  • The solution is to make the Comparator implement the order you want to have. Commented May 5, 2014 at 7:53

3 Answers 3

2

Implement your own comparator that tries to convert the objects to be compared to an integer, and if succesful, uses the compareTo of the Integer class, and otherwise uses the compareTo of the String class.

Like this:

public class MyComparator implements Comparator<String,String>
{
    public int compare(String s1, String s2)
   {
       try
       {
           int i1 = Integer.parseInt(s1);
           int i2 = Integer.parseInt(s2);
           return i1 - i2;
       }
       catch (NumberFormatException e)
       {
           return s1.compareTo(s2);
       }
   }
}

ArrayList<String> myList = (...);
Collections.sort(myList,new MyComparator());

As commented, this sorts like this 1,12,A102,A103. But wanted is: A102,A103,1,12. To do this we need to take care of situations where s1 is parsable as int and s2 is not and the other way around. I'm not sure if I got -1 and 1 right, so maybe they should be swapped.

public class MyComparator implements Comparator<String,String>
{
    public int compare(String s1, String s2)
   {
       Integer i1 = null
       Integer i2 = null
       try
       {
           i1 = Integer.parseInt(s1);
       }
       catch (NumberFormatException e) {}
       try
       {
           i2 = Integer.parseInt(s2);
       }
       catch (NumberFormatException e) {}
       if (i1 == null && i2 == null)
           return s1.compareTo(s2);
       if (i1 == null && i2 != null)
           return -1;
       if (i1 != null && i2 == null)
           return 1;
       return i1 - i2;
   }
}
Sign up to request clarification or add additional context in comments.

5 Comments

This. But there's a typo in the first parameter, should be String s1.
I would replace the body of the try {} block with new Integer(s1).compareTo(new Integer(s2)) or Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2)).
new Integer(String s) also calls parseInt() and throws a NFE, so that would purely be a matter of style.
But output is resulting in- 1 2 3 4 5 11 11 21 22 31 32 A101 A102 A103 A104 B405
That means we have to implement the situation where one is parsable to integer and the other is not.
0

Create a new "holder" object for the strings and implement the Comparable interface. Override the "compareTo" method. That should do the trick ;)

Comments

0

Answer is present there in your question, just create two lists and sort them separately!

package com.kvvssut.misc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class SortStringThenNumber {

    public static void main(String[] args) {
        List<String> inputs = Arrays.asList(new String[]{"1","5","3","4","2","11","11","21","31","32","22","A101","A103","A104","B405","A102"});
        List<Object> result = sortStringThenNumber(inputs);

        for (Object sorted : result) {
            System.out.println(String.valueOf(sorted));
        }
    }

    private static List<Object> sortStringThenNumber(List<String> inputs) {

        List<Integer> numbers = new ArrayList<Integer>();
        List<String> strings = new ArrayList<String>();

        for (String input : inputs) {
            if (input.matches("-?\\d+")) {
                numbers.add(Integer.valueOf(input));
            } else {
                strings.add(input);
            }
        }
        inputs = null;

        Collections.sort(numbers);
        Collections.sort(strings);

        ArrayList<Object> all = new ArrayList<Object>();
        all.addAll(strings);
        all.addAll(numbers);

        return all;
    }

}

1 Comment

output is - A101 A102 A103 A104 B405 1 2 3 4 5 11 11 21 22 31 32

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.