package peter; import java.util.Comparator; public enum DecimalComparator implements Comparator { LEADING_ZEROES_GREATER(1), LEADING_ZEROES_EQUAL(0), LEADING_ZEROES_LESS(-1); private final int leadingZeroesOrder; DecimalComparator(int leadingZeroesOrder) { this.leadingZeroesOrder = leadingZeroesOrder; } @Override public final int compare(CharSequence cs1, CharSequence cs2) { // count leading zeroes int len1 = cs1.length(); int z1 = leadingZeroes(cs1, len1); int len2 = cs2.length(); int z2 = leadingZeroes(cs2, len2); // compare length of the rest of sequences with leading zeroes stripped int cmp = Integer.compare(len1 - z1, len2 - z2); if (cmp != 0) return cmp; // stripped lengths match -> compare digits int i1 = z1; int i2 = z2; while (i1 < len1) { // assert i2 < l2; cmp = digit(cs1.charAt(i1)) - digit(cs2.charAt(i2)); if (cmp != 0) return cmp; i1++; i2++; } // digits match -> compare lengths of leading zeroes return Integer.compare(z1, z2) * leadingZeroesOrder; } private static int leadingZeroes(CharSequence cs, int len) { int i = 0; while (i < len && digit(cs.charAt(i)) == 0) i++; return i; } private static int digit(char c) { return (c >= '0' && c <= '9') ? (c - '0') // optimization for common ASCII case : Character.digit(c, 10); } }