You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java中List<Label>集合排序问题:实现百分比数值升序在前、字母不区分大小写排序在后

解决Label集合的自定义排序问题

你遇到的问题很典型——字符串默认排序逻辑和咱们实际需要的数值排序规则不匹配。先明确核心需求:带百分比的元素按数值升序排在最前面,剩余字母元素按不区分大小写的规则排序

当前使用的Comparator.comparing(Label::getLabel, String.CASE_INSENSITIVE_ORDER)之所以出错,是因为字符串排序是逐字符对比的:100%的第一个字符是1,比20%2小,所以字符串层面会判定100% < 20%,但咱们需要的是提取百分比中的数字,按数值大小排序。


解决方案一:自定义Lambda Comparator

直接写一个逻辑清晰的Comparator,分场景处理排序规则:

toReturn.sort((label1, label2) -> {
    String str1 = label1.getLabel();
    String str2 = label2.getLabel();

    // 判断是否为百分比格式(匹配1个或多个数字+百分号)
    boolean isPercent1 = str1.matches("\\d+%");
    boolean isPercent2 = str2.matches("\\d+%");

    // 规则1:百分比元素优先排在前面
    if (isPercent1 && !isPercent2) {
        return -1;
    }
    if (!isPercent1 && isPercent2) {
        return 1;
    }

    // 规则2:都是百分比时,提取数字转成整数比较大小
    if (isPercent1) {
        int num1 = Integer.parseInt(str1.replace("%", ""));
        int num2 = Integer.parseInt(str2.replace("%", ""));
        return Integer.compare(num1, num2);
    }

    // 规则3:都是普通字符串时,用不区分大小写排序
    return String.CASE_INSENSITIVE_ORDER.compare(str1, str2);
});

解决方案二:Java 8链式Comparator写法

如果更喜欢流式风格,可以把排序规则拆成多个Comparator链式组合,可读性拉满:

// 第一步:把非百分比元素排到后面
Comparator<Label> prioritizePercent = Comparator.comparing(
    label -> !label.getLabel().matches("\\d+%")
);

// 第二步:对百分比元素按数值排序,非百分比用MAX_VALUE不干扰排序
Comparator<Label> sortPercentByValue = Comparator.comparing(
    label -> {
        String s = label.getLabel();
        return s.matches("\\d+%") ? Integer.parseInt(s.replace("%", "")) : Integer.MAX_VALUE;
    }
);

// 第三步:普通字符串按不区分大小写规则排序
Comparator<Label> caseInsensitiveSort = Comparator.comparing(
    Label::getLabel, String.CASE_INSENSITIVE_ORDER
);

// 组合所有排序规则
toReturn.sort(prioritizePercent.thenComparing(sortPercentByValue).thenComparing(caseInsensitiveSort));

最终排序结果

两种写法运行后,都会得到你期望的正确顺序:

  • 百分比部分:0%10%20%40%100%(按数值升序)
  • 字母部分:Abcdbchbc(不区分大小写排序)

补充说明

  • 如果你的百分比包含小数(比如12.5%),可以把正则改成\d+(\.\d+)?%,同时把Integer换成Double来解析数值。
  • 如果Label类的label属性可能为null,记得在代码中添加空值判断,避免NullPointerException

内容的提问来源于stack exchange,提问作者Santosh Kamat

火山引擎 最新活动