How to Sort Strings w/ Numbers in Java
In this post, I explain the problem of sorting strings that contain numbers. If you just sort values using the default approach, it will not work properly. For example, it will sort “a10″ before “a2″ even though in your application you may want it to consider the alphabetic characters separately from the numeric ones in sorting. Or in other words, because the first character is the same, you may want it to treat the remaining portions as numbers. So “a2″ would be sorted before “a10″ because 2 is less than 10.
I converted the Python code from the other post to Java code. I won’t explain how it works, but let me know if you want an explanation.
import java.util.*; public class NumericString implements Comparable { private String _rawValue; public NumericString(String rawValue) { _rawValue = rawValue; } private static int CompareTwoVals(String xVal, String yVal) { if (IsDouble(xVal) && IsDouble(yVal)) return new Double(Double.parseDouble(xVal)).compareTo(Double.parseDouble(yVal)); if (!IsDouble(xVal) && !IsDouble(yVal)) return xVal.compareTo(yVal); if (IsDouble(xVal)) return -1; return 1; } private ArrayList GetValueList() { ArrayList valueList = new ArrayList(); String tempVal = ""; for (int i=0; i<_rawValue.length(); i++) { String val = _rawValue.substring(i, i+1); if (IsDouble(val)) tempVal += val; else { if (!tempVal.equals("")) { valueList.add(tempVal); tempVal = ""; } valueList.add(val); } } if (!tempVal.equals("")) valueList.add(tempVal); return valueList; } public static boolean IsDouble(String value) { try { Double.parseDouble(value); return true; } catch (Exception ex) { return false; } } @Override public int compareTo(Object obj) { if (obj == null) return -1; NumericString compareObj = (NumericString)obj; if (this._rawValue == null) return -1; if (compareObj._rawValue == null) return 1; if (this._rawValue.equals(compareObj._rawValue)) return 0; ArrayList xList = this.GetValueList(); ArrayList yList = compareObj.GetValueList(); for (int i=0; i<xList.size() && i<yList.size(); i++) { int compareResult = CompareTwoVals(xList.get(i), yList.get(i)); if (compareResult != 0) return compareResult; } return new Integer(xList.size()).compareTo(yList.size()); } @Override public String toString() { return _rawValue; } }
Here’s how you might call it:
NumericString a = new NumericString("a10"); NumericString b = new NumericString("a2"); ArrayList list = new ArrayList(); list.add(a); list.add(b); Collections.sort(list); for (NumericString x : list) System.out.println(x); // a2, a10
