简体   繁体   中英

How to sort Alphanumeric String with letters before numbers (ascending order)

I have a of Strings with this order:

Collections.sort(alTest);

1G0EE147546
1G1EE147576
1G3EE147547
1G4EE147577
1G6EE147548
1G6EE147574
1G7EE147578
1G8EE147545
1G9EE147575
1GXEE147579

Note the last record 1G EE147579, when "X" comes after "9" 1G EE147575. EE147579,当“X”出现在“9”1G EE147575 之后。

And I need this list to be sorted this way:

1GXEE147579
1G0EE147546
1G1EE147576
1G3EE147547
1G4EE147577
1G6EE147548
1G6EE147574
1G7EE147578
1G8EE147545
1G9EE147575

With "X" of 1G EE147579 before the numbers "0","1", etc. 1G EE147546 EE147579 的“X” 1G EE147546

Thank you

You can write your own comparator to adjust sorting condition to your requirements:

    private static final Comparator<String> comparator = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            //here comes the comparing process
            return 0;
        }
    };

Comparator returns one of three values:

  • -1 when the o1 object should be placed before o2 in order
  • 1 when the o1 object should be placed after o2 in order
  • 0 when comparing objects are equal

Then you can use it in that way(notice that to use Collections.sort(...) function you have to use list structure):

        Collections.sort(list, comparator);

To give some hint about this specific sort I can recommend you to specify whether every character in string should be sorted in that way(letters before numbers). Just loop over string characters and compare them. To check if character is a digit use Character.isDigit(...) .

Here a simple comparator example to do what you want.

Edit : You can also add the comparator to you Set as a TreeSet instead of HashSet .

Set<String> datas = new TreeSet<>(new SimpleComparator());

You can refers to the javadoc for more details

    static class SimpleComparator implements Comparator<String> {
        @Override
        public int compare(String s, String s2)
        {
            if(s == s2)
                return 0;
            if(s != null && s2 == null)
                return -1;
            if(s == null && s2 != null)
                return 1;
            return (s.charAt(2) == 'X' ? s.substring(0, 2) + ' ' + s.substring(3) : s).compareTo(s2);
        }
    }

    @Test
    public void sort() throws Exception{

        List<String> data =  Arrays.asList(
                "1G0EE147546",
                "1G1EE147576",
                "1G3EE147547",
                "1G4EE147577",
                "1G6EE147548",
                "1G6EE147574",
                "1G7EE147578",
                "1G8EE147545",
                "1G9EE147575",
                "1GXEE147579"

        );
        Collections.sort(data, new SimpleComparator());
        System.out.println(data.toString().replaceAll(",", "\n"));
    }

Here are some inputs:

  1. You can't sort HashSet . Collections#sort consumes List . You can create the ArrayList passing the Set into Constructor
Set<String> hsNr = new HashSet<String>();
ArrayList list = new ArrayList(hsNr);
  1. For sorting the list the way you need you can pass Comparator as 2nd param to Collections#sort :
        Collections.sort(list, new Comparator<String>() {
            public int compare(String o1, String o2) {
                // write your implementation here
                // return ...  
            }
        });
  1. You can take take a look at the standard impl on strings comparing and use it as example to create the Comparator : java.lang.StringUTF16#compareTo(byte[], byte[])

I implemented it using Java 8 streams:

    public List<String> specialSort(Set<String> hsNr) {
        return hsNr.stream()
                .sorted((a, b) -> a.charAt(2) == 'X' ? b.compareTo(a) : a.compareTo(b))
                .collect(Collectors.toList());
    }

Sets can't be sorted, because order is not guaranteed. Notice that you don't have a get(index) method when working with a set.

Create a custom Collator using the RuleBasedCollator class:

String rules = "< a, A < b, B < c, C < d, D < e, E < f, F < g, G < h, H < i, I" +
              " < j, J < k, K < l, L < m, M < n, N < o, O < p, P < q, Q < r, R" +
              " < s, S < t, T < u, U < v, V < w, W < x, X < y, Y < z, Z" +
              " < 0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9";
RuleBasedCollator myCollator = new RuleBasedCollator(rules);

List<String> list = Arrays.asList(
        "1G7EE147578", "1G6EE147548", "1G1EE147576", "1G0EE147546", "1G8EE147545",
        "1G4EE147577", "1G6EE147574", "1GXEE147579", "1G9EE147575", "1G3EE147547");
System.out.println("Before: " + list);
Collections.sort(list, myCollator);
System.out.println("After:  " + list);

Output

Before: [1G7EE147578, 1G6EE147548, 1G1EE147576, 1G0EE147546, 1G8EE147545, 1G4EE147577, 1G6EE147574, 1GXEE147579, 1G9EE147575, 1G3EE147547]
After:  [1GXEE147579, 1G0EE147546, 1G1EE147576, 1G3EE147547, 1G4EE147577, 1G6EE147548, 1G6EE147574, 1G7EE147578, 1G8EE147545, 1G9EE147575]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM