1

there are some values like AB, A012B, CD,1,10,01,9 I HAVE TO SORT THE THEM the output shud be 01,1,9,10,A012B,AB,CD can use any collection im trying to use collection.sort function but its considering everything as string and printing like 01,1,10,9,A012B,AB,CD its not my req... Pls help

5 Answers 5

3

//the fishing technique

List<String> values = new ArrayList<String>();
    values.add("AB");
    values.add("A012B");
    values.add("CD");
    values.add("1");
    values.add("10");
    values.add("01");
    values.add("9");
    values.add("I");
    Collections.sort(values, new Comparator<String>() {

        @Override
        public int compare(String o1, String o2) {
            // TODO tweak the comparator here 
            try{
            Integer integer1 = Integer.valueOf(o1);
            Integer integer2 = Integer.valueOf(o2);
            return integer1.compareTo(integer2);
            }catch (java.lang.NumberFormatException e) {
                return o1.compareTo(o2);
            }
        }
    });
    System.out.println(values);
}

//not enough???

//here is the fish

public static void main(String[] args) throws Exception {
    List<String> values = new ArrayList<String>();
    values.add("AB");
    values.add("A012B");
    values.add("CD");
    values.add("1");
    values.add("10");
    values.add("01");
    values.add("9");

    int maxLen = 0;
    for (String string : values) {
        if (string.length() > maxLen) {
            maxLen = string.length();
        }
    }

    Collections.sort(values, new MyComparator(maxLen));

    System.out.println(values);
}

public static class MyComparator implements Comparator<String> {
    private int maxLen;
    private static final String REGEX = "[0-9]+";

    public MyComparator(int maxLen) {
        this.maxLen = maxLen;

    }

    @Override
    public int compare(String obj1, String obj2) {
        String o1 = obj1;
        String o2 = obj2;
        // both numbers
        if (o1.matches("[1-9]+") && o2.matches("[1-9]+")) {
            Integer integer1 = Integer.valueOf(o1);
            Integer integer2 = Integer.valueOf(o2);
            return integer1.compareTo(integer2);
        }

        // both string
        if (o1.matches("[a-zA-Z]+") && o2.matches("[a-zA-Z]+")) {
            return o1.compareTo(o2);
        }

        Pattern p = Pattern.compile(REGEX);
        Matcher m1 = p.matcher(o1);
        Matcher m2 = p.matcher(o2);

        List<String> list = new ArrayList<String>();
        while (m1.find()) {
            list.add(m1.group());
        }
        for (String string : list) {
            o1.replaceFirst(string, leftPad(string, "0", maxLen));
        }

        list.clear();

        while (m2.find()) {
            list.add(m2.group());
        }
        for (String string : list) {
            o2.replaceFirst(string, leftPad(string, "0", maxLen));
        }
        return o1.compareTo(o2);

    }
}

public static String leftPad(String stringToPad, String padder, Integer size) {

    final StringBuilder strb = new StringBuilder(size.intValue());
    final StringCharacterIterator sci = new StringCharacterIterator(padder);

    while (strb.length() < (size.intValue() - stringToPad.length())) {
        for (char ch = sci.first(); ch != CharacterIterator.DONE; ch = sci.next()) {
            if (strb.length() < (size.intValue() - stringToPad.length())) {
                strb.insert(strb.length(), String.valueOf(ch));
            }
        }
    }

    return strb.append(stringToPad).toString();
}
Sign up to request clarification or add additional context in comments.

3 Comments

i think, all is fine except, i want "01" before "1". Any idea on how can we achieve that??? the output is coming as 1,01,9,A01B,AB,CD
Thanks a lot.. I really appreciate your effort
First off, great code. One exception...10 should come after 9 and does not. For example, list={2,10,1,21,9} should come out as 1,2,9,10,21 but comes out as 1,10,2,21,9 Could you update the answer to fix it? Please :)
1

you should implement a comparator:

given Object O1 and Object O2:

you first try to conver them to numbers and compare numbers.

if O1 is numeric and O2 is not, then O2 is to be conisdered greater than O1

if O1 is not numeric and O2 is numeric, then O1 is to be considered greater than O1

if both are not numeric, you compare them as strings.

Comments

1

You have to implement Comparator. I assume that all your data is in the form of Strings. Therefore by default "10" comes before "9" . You need to fix that by implementing java.util.Comparator yourself.

Comments

0

First you write your own Comparator and then you call Collections.sort(List, Comparator)

Comments

0

User952887's answer is great except it still gives 0,01,1,10,11,2,21,3,4,5,...etc (notice 10 comes after 1 and before 2). Look to the following link for a great alphanumeric comparator that will return 0,1,2,3,4,5,10,11,21 http://sanjaal.com/java/tag/sample-alphanumeric-sorting/ The only problem is that it will return 0,1,01-which User952887's fixed.

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.