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;
    }
}

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