Java中如何对含字母数字属性的对象进行自然排序?
解决字符串含数字的自然排序问题
你遇到的是默认字典序排序与自然排序的差异问题。默认字符串比较会逐个对比字符ASCII码,"A-Product-12"里的第一个数字字符'1'比"A-Product-2"里的'2'ASCII码小,所以排序结果不符合预期。要实现按名称中数字的实际大小排序,需要自定义比较逻辑:
1. 自定义比较器实现自然排序
import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ProductNameComparator implements Comparator<Product> { // 匹配名称末尾数字的正则表达式 private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d+)$"); @Override public int compare(Product p1, Product p2) { // 提取名称中的数字部分 Integer num1 = extractNumber(p1.name); Integer num2 = extractNumber(p2.name); // 先比较名称的非数字前缀 String prefix1 = p1.name.replaceAll("\\d+$", ""); String prefix2 = p2.name.replaceAll("\\d+$", ""); int prefixCompare = prefix1.compareTo(prefix2); if (prefixCompare != 0) { return prefixCompare; } // 前缀相同时,按数字大小排序 return num1.compareTo(num2); } private Integer extractNumber(String name) { Matcher matcher = NUMBER_PATTERN.matcher(name); if (matcher.find()) { return Integer.parseInt(matcher.group(1)); } return 0; // 无数字时默认按0处理 } }
2. 应用自定义比较器排序
直接对列表排序
products.sort(new ProductNameComparator());
通过Stream流排序
List<Product> sortedProducts = products.stream() .sorted(new ProductNameComparator()) .toList();
补充说明
如果产品名称中的数字位置不固定(比如中间也包含数字),可以调整正则表达式匹配所有数字段;若不想手动实现,也可以使用Apache Commons Lang工具包中的StringUtils.naturalCompare方法,但自定义比较器无需引入第三方依赖,完全能满足需求。
内容的提问来源于stack exchange,提问作者ardiafrizky
相关产品推荐
相关产品推荐

