java排序混乱的字符串字母和数字排序



前言

大概内容:

因为java默认的自然排序算法,会把G2, G1, G11, G9,G16, G4排序成G1, G11, G16, G2, G4, G9,针对这种情况我封装了一个工具类,排序后得到的是G1, G2 , G4, G9, G11, G16;

简单说明实现的逻辑

就是把List先根据字符串字母部分分组,得到一个Map<String,List<String>>也可以说是Map<字母部分,List<数字部分>>,对每个map的元素的数字部分数组排序,排序后拼接还原成List返回

适用的字符串类型

例如:
你好1,你好2,我好3 //先根据汉字的音法排序,再根据数字排序
A1,wAD1,A2,a1,h1,W1,W3 // 先根据字母顺序排序,再根据数字部分排序
A1-1,a2-3,V1-1,A2-1 //先根据字母排序,然后根据-前面的数字排序,再根据-后面的数字排序,-可以为任意符号


提示:以下是本篇文章正文内容,下面案例可供参考

测试结果


原始数据:[GXC(WS)2-2, GXC(WS)1-3, GXC(WS)1-1, GXC(GS)2, GXC(WS)2-1, GXC(GS)1, GXC(GS)17-1, GXC(GS)8, GXC(GS)6, GXC(GS)6, GXC(GS)2, ]
自然排序:[, GXC(GS)1, GXC(GS)17-1, GXC(GS)2, GXC(GS)2, GXC(GS)6, GXC(GS)6, GXC(GS)8, GXC(WS)1-1, GXC(WS)1-3, GXC(WS)2-1, GXC(WS)2-2]
调用工具类排序:[GXC(GS)1, GXC(GS)2, GXC(GS)2, GXC(GS)6, GXC(GS)6, GXC(GS)8, GXC(GS)17-1, GXC(WS)1-1, GXC(WS)1-3, GXC(WS)2-1, GXC(WS)2-2]

测试


    public static void main(String[] args) {
        //原始数据
        ArrayList<String> objects = new ArrayList<>();
        objects.add("GXC(WS)2-2");
        objects.add("GXC(WS)1-3");
        objects.add("GXC(WS)1-1");
        objects.add("GXC(GS)2");
        objects.add("GXC(WS)2-1");
        objects.add("GXC(GS)1");
        objects.add("GXC(GS)17-1");
        objects.add("GXC(GS)8");
        objects.add("GXC(GS)6");
        objects.add("GXC(GS)6");
        objects.add("GXC(GS)2");
        objects.add("");
        System.err.println("原始数据:"+objects);
        
        //自然排序
        objects.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        System.err.println("自然排序:"+objects);
        
        System.err.println("调用工具类排序:"+compareStrList(objects));
    }

封装的工具类


import cn.hutool.core.util.StrUtil;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description: 测点排序工具类
 * @Param:
 * @return:
 * @Author: 杨永卓
 * @Date: 2022年7月13日09:53:493
 */
public class PointSortUtil {
    //正负数小数正则表达式
    private static final String REGEX_NUM = "^[-\\+]?([0-9]+\\.?)?[0-9]+$";
        //自定义字符格式
    private static final String CHAR_TYPE = "-";

    /**
     * @Description: 对List混合字符串排序
     * @Param: o1:对list混合字符串排序,o2:对list混合字符串排序   例如:SDD1-1/SDD1
     * @return: 1大于      0等于    -1小于
     * @Author: 杨永卓
     * @Date: 2022年7月18日14:32:44
     */
    public static List<String> compareStrList(List<String> stringList) {
        //返回对象
        List<String> result = new ArrayList<>();

        //转Map,并排序字母部分
        HashMap<String, List<String>> map = getHashMap(stringList);
        List<String> sortKey = map.keySet()
                .stream()
                .sorted()
                .collect(Collectors.toList());
        for (String key : sortKey) {
            List<String> valueList = map.get(key);
            valueList.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    String[] split1 = o1.split(CHAR_TYPE);
                    String[] split2 = o2.split(CHAR_TYPE);
                    if (!getValueIsNumber(split1[0]) || !getValueIsNumber(split2[0])) {
                        return -1;
                    }
//                  排序
                    if (Integer.parseInt(split1[0]) > Integer.parseInt(split2[0])) {
                        return 1;
                    } else if (Integer.parseInt(split1[0]) == Integer.parseInt(split2[0])) {
                        if (split1.length == 2 && split2.length == 2) {
                            if (Integer.parseInt(split1[1]) > Integer.parseInt(split2[1])) {
                                return 1;
                            } else if (Integer.parseInt(split1[1]) == Integer.parseInt(split2[1])) {
                                return 0;
                            }
                            return -1;
                        }
                        return 0;
                    }
                    return -1;
                }
            });
            for (String value : valueList) {
                result.add(key + value);
            }
        }
        return result;
    }

    /**
     * 查询字符串中正则筛选后第一次出现和最后一次出现的下标
     *
     * @param str 查询的字符串,status:0起始下标 1结束下标 ,regexp:正则
     * @return 若存在,返回位置索引,否则返回-1;
     * 杨永卓
     * 2022年7月13日09:57:36
     */
    private static Map<String, Integer> findIndexNumberOfStr(String str, String regexp) {
        int start = -1;
        int end = -1;
        Map<String, Integer> map = new HashMap<>();
        char[] chars = str.toCharArray();
        for (int n = 0; n < chars.length; n++) {
            String value = String.valueOf(chars[n]);
            boolean b = value.matches(regexp);
            if (b) {
                if (start > -1) {
                    end = n;
                } else {
                    start = n;
                    end = n;
                }
            } else {
                if (start > -1) {
                    map.put("startIndex", start);
                    map.put("endIndex", end);
//                    return map;
                }
            }
        }
        map.put("startIndex", start);
        map.put("endIndex", end);
        return map;
    }

    /**
     * 2022年7月13日09:57:30
     * 杨永卓
     * 判断字符串是否为纯数字
     */
    private static boolean getValueIsNumber(String thisValue) {
        if (StrUtil.isEmpty(thisValue)) return false;
        return thisValue.matches(REGEX_NUM);
    }

    /**
     * @Description: 把字符串数组拆解转为HashMap返回
     * @Param:
     * @return:
     * @Author: 杨永卓
     * @Date: 2022/7/18 14:09
     */
    private static HashMap getHashMap(List<String> strList) {
        HashMap<String, List<String>> map = new HashMap<>();
        for (String str : strList) {
            if (StrUtil.isEmpty(str)) continue;
            // 截取数字部分的下标,生成key和value值
            Map<String, Integer> map1 = findIndexNumberOfStr(str, "^[0-9]+$");
            String start = str.substring(0, map1.get("startIndex"));
            String end = str.substring(map1.get("startIndex"), map1.get("endIndex") + 1);

            List<String> strings = map.get(start);
            if (null == strings) {
                map.put(start, new ArrayList<>(Arrays.asList(end)));
            } else {
                strings.add(end);
            }
        }
        return map;
    }
}


总结:仰天大笑出门去,我辈岂是蓬蒿人

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用Java中的`Comparator`接口自定义排序规则来实现字符串按照字母数字排序。具体步骤如下: 1. 定义一个实现了`Comparator`接口的类,重写`compare`方法。 2. 在`compare`方法中,对两个字符串进行比较,返回比较结果。 1. 如果两个字符串在相同位置上的字符相同,继续比较下一个字符; 2. 如果两个字符串在相同位置上的字符不同,按照字符的ASCII码大小进行比较,ASCII码小的排在前面; 3. 如果一个字符串的某个位置上没有字符,认为它的字符比另一个字符串的相应位置上的字符小,排在前面。 以下是示例代码: ```java import java.util.Arrays; import java.util.Comparator; public class StringSort { public static void main(String[] args) { String[] arr = {"a123", "c", "b", "123", "A", "B", "c123"}; Arrays.sort(arr, new MyComparator()); System.out.println(Arrays.toString(arr)); } } class MyComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { int i = 0, j = 0; while (i < o1.length() && j < o2.length()) { char c1 = o1.charAt(i), c2 = o2.charAt(j); if (c1 == c2) { i++; j++; } else if (Character.isDigit(c1) && Character.isDigit(c2)) { int num1 = 0, num2 = 0; while (i < o1.length() && Character.isDigit(o1.charAt(i))) { num1 = num1 * 10 + o1.charAt(i) - '0'; i++; } while (j < o2.length() && Character.isDigit(o2.charAt(j))) { num2 = num2 * 10 + o2.charAt(j) - '0'; j++; } if (num1 != num2) { return num1 - num2; } } else { return c1 - c2; } } return o1.length() - o2.length(); } } ``` 运行结果为: ``` [A, B, a123, b, c, c123, 123] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT行业小趴菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值