开发者

how to sort a collection which has strings, integers and alphanumerics in java

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,A012开发者_JAVA技巧B,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


//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();
}


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.


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.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜