Java 8 Comparator实现自定义对象按邮编+Roll降序排序异常问题
解决AreaModel按pinCode和rollNo数字部分排序的问题
当前代码对rollNo使用字符串反向排序时,是基于ASCII字典序比较的,这导致"ROLE-45"这类带前缀的字符串会排在纯数字字符串"70"前面(因为'R'的ASCII码大于'7'),但实际需求是按rollNo中包含的数字值降序排序,因此需要自定义比较逻辑提取数字部分进行比较。
解决方案
- 编写工具方法提取
rollNo中的数字部分,转换为数值类型 - 修改Comparator,在pinCode排序后,基于提取的数字值进行降序排序
修改后的完整代码
MainClass代码
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import com.javainuse.model.AreaModel; public class MainClass { // 提取rollNo中的数字部分 private static Long extractRollNumber(String rollNo) { Pattern numberPattern = Pattern.compile("\\d+"); Matcher matcher = numberPattern.matcher(rollNo); if (matcher.find()) { return Long.parseLong(matcher.group()); } // 无数字时返回0,可根据实际需求调整 return 0L; } public static void main(String[] args) { List<AreaModel> list = new ArrayList<AreaModel>(); list.add(new AreaModel(535005, "2")); list.add(new AreaModel(535006, "100")); list.add(new AreaModel(535007, "30")); list.add(new AreaModel(535005, "ROLE-45")); list.add(new AreaModel(535005, "ROLE-10")); list.add(new AreaModel(535005,"13")); list.add(new AreaModel(535005,"70")); // 自定义排序规则:先按pinCode升序,再按rollNo中的数字降序 Comparator<AreaModel> areaComparator = Comparator.comparing(AreaModel::getPinCode) .thenComparing(area -> extractRollNumber(area.getRollNo()), Comparator.reverseOrder()); list = list.stream().sorted(areaComparator).collect(Collectors.toList()); System.out.println("***"); System.out.println(list); } }
运行结果
运行后会输出预期结果:
*** [[535005 70], [535005 ROLE-45], [535005 13], [535005 ROLE-10], [535005 2], [535006 100], [535007 30]]
关键说明
extractRollNumber方法通过正则表达式\\d+匹配字符串中的连续数字,将其转换为Long类型,确保按数值大小比较而非字符串字典序- 排序时先按
pinCode自然升序,再通过thenComparing传入数字提取逻辑和反向排序规则,实现需求中的多级排序
内容的提问来源于stack exchange,提问作者Kishore Kumar Korada
相关产品推荐
相关产品推荐

