/** * 自然排序比较器 */ public final class NaturalOrderComparator<T> implements Comparator<T> { private final boolean caseInsensitive; public NaturalOrderComparator(boolean caseInsensitive) { this.caseInsensitive = caseInsensitive; } private int compareRight(String a, String b) { int bias = 0; int ia = 0; int ib = 0; for (; ; ia++, ib++) { char ca = charAt(a, ia); char cb = charAt(b, ib); if (!Character.isDigit(ca) && !Character.isDigit(cb)) { return bias; } else if (!Character.isDigit(ca)) { return -1; } else if (!Character.isDigit(cb)) { return +1; } else if (ca < cb) { if (bias == 0) { bias = -1; } } else if (ca > cb) { if (bias == 0) { bias = +1; } } else if (ca == 0 && cb == 0) { return bias; } } } @Override public int compare(T o1, T o2) { String a = o1.toString(); String b = o2.toString(); int ia = 0, ib = 0; int nza = 0, nzb = 0; char ca, cb; int result; while (true) { nza = nzb = 0; ca = charAt(a, ia); cb = charAt(b, ib); while (ca == '0') { nza++; if (!Character.isDigit(charAt(a, ia + 1))) { break; } ca = charAt(a, ++ia); } while (cb == '0') { nzb++; if (!Character.isDigit(charAt(b, ib + 1))) { break; } cb = charAt(b, ++ib); } if (Character.isDigit(ca) && Character.isDigit(cb)) { if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) { return result; } } if (ca == 0 && cb == 0) { return nza - nzb; } if (ca < cb) { return -1; } else if (ca > cb) { return +1; } ++ia; ++ib; } } private char charAt(String s, int i) { if (i >= s.length()) { return 0; } else { return caseInsensitive ? Character.toUpperCase(s.charAt(i)) : s.charAt(i); } } }
public class Test { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("A1"); list.add("A2"); list.add("A40"); list.add("A10"); list.add("A110"); list.add("A112"); list.add("A3"); list.add("A04"); Collections.sort(list, new NaturalOrderComparator<>(true)); list.forEach(item -> System.out.println(item)); } }
执行结果:
A1
A2
A3
A04
A10
A40
A110
A112