package net.techreadiness.util; import java.util.Comparator; /** * * * This is a case-insensitive comparator to compare strings alphanumerically. Normally when sorting grades, you would see: * Grade 1 Grade 12 Grade 13 Grade 2 Grade 21 Grade 3 ... etc. * * This comparator compares the entire number, so you get Grade 1 Grade 2 Grade 3 Grade 12 Grade 13 Grade 21 ... etc. * */ public class NumericStringComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { return compareStrings(o1, o2); } public static int compareStrings(String s1, String s2) { if (s1 == null) { s1 = ""; } if (s2 == null) { s2 = ""; } int i1 = 0, i2 = 0; while (i1 < s1.length() && i2 < s2.length()) { @SuppressWarnings("rawtypes") Comparable c1, c2; int j1 = isNumeric(s1, i1); int j2 = isNumeric(s2, i2); if (j1 > 9) { j1 = 9; } if (j2 > 9) { j2 = 9; } if (j1 != 0 && j2 != 0) { c1 = new Integer(s1.substring(i1, i1 + j1)); c2 = new Integer(s2.substring(i2, i2 + j2)); i1 += j1; i2 += j2; } else { c1 = s1.substring(i1, i1 + 1).toUpperCase(); c2 = s2.substring(i1, i1 + 1).toUpperCase(); i1++; i2++; } @SuppressWarnings("unchecked") int c = c1.compareTo(c2); if (c != 0) { return c; } } return s1.length() - s2.length(); } /** * int isNumeric(String s, int index) * * @params: s - the to check index - location in s to check * * @returns: number of sequential numeric characters in s, starting at index */ private static int isNumeric(String s, int index) { int ret = 0; if (index < s.length()) { char c = s.charAt(index); while (Character.isDigit(c)) { ret++; if (index + ret < s.length()) { c = s.charAt(index + ret); } else { c = (char) -1; } } } return ret; } }