如何实现Java自定义尺寸字符串Comparator完成带单位字符串排序
实现方案
核心逻辑是先把每个待比较的字符串拆分为数值部分和单位部分,再按规则分步比较:
- 第一步比较单位的字典序,g天然排在ml前面
- 单位相同时,比较数值大小,按升序排列
完整代码实现
import java.math.BigDecimal; protected int compareInstances(String instance1, String instance2) { // 拆分instance1的数值和单位 String[] split1 = splitValueAndUnit(instance1); BigDecimal value1 = new BigDecimal(split1[0]); String unit1 = split1[1]; // 拆分instance2的数值和单位 String[] split2 = splitValueAndUnit(instance2); BigDecimal value2 = new BigDecimal(split2[0]); String unit2 = split2[1]; // 先按单位字典序排序 int unitCompare = unit1.compareTo(unit2); if (unitCompare != 0) { return unitCompare; } // 单位相同则按数值升序排序,用BigDecimal避免浮点精度问题 return value1.compareTo(value2); } /** * 拆分字符串为数值部分和单位部分 * @param str 待拆分的字符串,格式为[数字][单位],例如50ml、100g * @return 长度为2的数组,下标0是数值字符串,下标1是单位字符串 */ private String[] splitValueAndUnit(String str) { // 找到第一个非数字、非小数点的位置,就是单位的起始位置 int unitStartIndex = 0; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (!Character.isDigit(c) && c != '.') { unitStartIndex = i; break; } } String valueStr = str.substring(0, unitStartIndex); String unitStr = str.substring(unitStartIndex); return new String[]{valueStr, unitStr}; }
逻辑说明
- 拆分逻辑:遍历字符串找到第一个既不是数字也不是小数点的位置,以此为界拆分数值和单位,适配整数、小数的数值格式
- 单位比较直接用String自带的字典序比较,刚好符合
g排在ml前面的要求 - 数值比较用BigDecimal而不是double/float,避免小数精度丢失导致排序错误
- 如果业务场景存在不符合格式的输入,可以在splitValueAndUnit方法里增加异常捕获,异常时直接返回原字符串的compareTo结果作为兜底即可
内容的提问来源于stack exchange,提问作者Nexussim Lements
相关产品推荐
相关产品推荐

