前言
java项目对于对象的混合字符串例如:[a4, a4, b2, B3, a7, b3, A1, a1, a3, B2, A2, b1, a2, B1]
排序,会出现A1,A13,A15,A2,A24
这样的排序混乱情况,下面是我封装的工具类根据数字部分进行排序,可以直接拿走使用,排序后[A1, A2, B1, B2, B3, a1, a2, a3, a4, a4, a7, b1, b2, b3]
,如果是要先根据字母排序再根据数字排序,也很简单,下面第二个就是
提示:以下是本篇文章正文内容,下面案例可供参考
工具类代码
import cn.hutool.core.util.StrUtil;
import java.util.*;
/**
* @Description: 测点排序工具类
* @Param:
* @return:
* @Author: 杨永卓
* @Date: 2022年7月13日09:53:493
*/
public class PointSortUtil {
//正负数小数正则表达式
private static final String REGEX_NUM = "^[-\\+]?([0-9]+\\.?)?[0-9]+$";
/**
* @Description: 用来对两个混合数字排序
* @Param: o1混合数字 o2混合数字
* @return: 1大于 0等于 -1小于
* @Author: 杨永卓
* @Date: 2022/7/13 15:26
*/
public static int compare(String o1, String o2) {
if (StrUtil.isEmpty(o1)) {
return -1;
} else if (StrUtil.isEmpty(o2)) {
return 1;
} else if (StrUtil.isEmpty(o1) && StrUtil.isEmpty(o2)) {
return -1;
}
// 截取线路数字部分的下标
Map<String, Integer> map1 = findIndexNumberOfStr(o1, "^[0-9]+$");
Map<String, Integer> map2 = findIndexNumberOfStr(o2, "^[0-9]+$");
if (-1 == map1.get("startIndex") || -1 == map1.get("endIndex") || -1 == map2.get("startIndex") || -1 == map2.get("endIndex")) {
return -1;
}
// 转换字符串
String str1 = o1.substring(map1.get("startIndex"), map1.get("endIndex") + 1);
String str2 = o2.substring(map2.get("startIndex"), map2.get("endIndex") + 1);
if (!getValueIsNumber(str1) || !getValueIsNumber(str2)) {
return -1;
}
// 排序
if (Integer.parseInt(str1) > Integer.parseInt(str2)) {
return 1;
} else if (Integer.parseInt(str1) == Integer.parseInt(str2)) {
return 0;
}
return -1;
}
/**
* @Description: 用来对两个混合数字的首字母排序
* @Param: o1混合数字 o2混合数字
* @return: 1大于 0等于 -1小于
* @Author: 杨永卓
* @Date: 2022/7/13 15:26
*/
public static int compareChar(String o1, String o2) {
if(o1.charAt(0)>o2.charAt(0)) return 1;
else if(o1.charAt(0)==o2.charAt(0)) return 0;
else return -1;
}
/**
* 查询字符串中正则筛选后第一次出现和最后一次出现的下标
*
* @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 {
// 如果线路为 S1号线1 S1号线2 则取中间的数字并返回
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);
}
}
业务层调用
一、只根据字符串的数字部分排序,业务层调用
List<User> users=new ArrayList();
//如果测项名称相同就手动排序
if(users.size()>0){
String itemName = users.get(0).getItemName();
if("中文".equals(itemName)||"汉语".equals(itemName)){
users.sort(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
//这里调用工具类实现排序
return PointSortUtil.compare(o1.getPointName(),o2.getPointName());
}
});
}
}
二、先根据字符串的首字母排序,再根据数字部分排序
List<User> users=new ArrayList();
//如果测项名称相同就手动排序
if(users.size()>0){
String itemName = users.get(0).getItemName();
if("中文".equals(itemName)||"汉语".equals(itemName)){
users.sort(new Comparator<User>() {
@Override
public int compare(User o1, Usero2) {
return PointSortUtil.compareChar(o1.getName(),o2.getName());
}
}.thenComparing(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return PointSortUtil.compare(o1.getName(),o2.getName());
}
}))
}
}