基于Java 8实现带多下划线的字符串列表按整数规则排序
问题描述
需要仅使用Java 8对包含多个下划线的String类型ArrayList按整数规则排序,原始数据示例如下:
List<String> keyValues = new ArrayList<String>(); keyValues.add("100_10_20_1"); keyValues.add("100001"); keyValues.add("100002"); keyValues.add("100002_1"); keyValues.add("100003"); keyValues.add("100"); keyValues.add("100_1"); keyValues.add("100_2"); keyValues.add("100_1_1"); keyValues.add("100_10_20"); keyValues.add("10000001"); keyValues.add("100_10_20_2");
此前尝试过将下划线替换为0或空字符串,但会出现数值冲突;替换为点转为Double类型则触发异常。指定的排序逻辑为:前缀相同的短字符串排在前面,同一前缀下按后续整数值从小到大排序,示例逻辑如下:
100 100_1 100_1_2 /after that only/ 100_2 100_2_2 /after that/ 103 104 105 10000 /similarly the pattern repeats/ 10000_1 10000_2 10000_2_1 100002
期望排序结果:
100 100_1 100_1_1 100_2 100_10_20 100_10_20_1 100_10_20_2 100001 100002 100002_1 100003 10000001
解决方案
核心思路是将每个字符串按下划线分割为整数数组,然后逐个比较数组中的元素:
- 依次比较两个数组对应位置的整数值,遇到不同值直接返回比较结果
- 如果一个数组是另一个的前缀,则短数组对应的字符串排在前面
具体实现代码如下:
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class StringIntegerSort { public static void main(String[] args) { List<String> keyValues = new ArrayList<>(); keyValues.add("100_10_20_1"); keyValues.add("100001"); keyValues.add("100002"); keyValues.add("100002_1"); keyValues.add("100003"); keyValues.add("100"); keyValues.add("100_1"); keyValues.add("100_2"); keyValues.add("100_1_1"); keyValues.add("100_10_20"); keyValues.add("10000001"); keyValues.add("100_10_20_2"); // Java 8 排序实现 List<String> sortedList = keyValues.stream() .sorted(Comparator.comparing( s -> java.util.Arrays.stream(s.split("_")) .map(Long::parseLong) .collect(Collectors.toList()), (list1, list2) -> { int minLength = Math.min(list1.size(), list2.size()); for (int i = 0; i < minLength; i++) { int compare = list1.get(i).compareTo(list2.get(i)); if (compare != 0) { return compare; } } // 短列表在前 return Integer.compare(list1.size(), list2.size()); } )) .collect(Collectors.toList()); // 输出结果 sortedList.forEach(System.out::println); } }
代码说明
- 使用
split("_")将字符串分割为子串,再转为Long类型(避免整数溢出,比如10000001这类大数值) - 自定义Comparator比较两个整数列表:先逐一比较对应位置的数值,若全部相同则比较列表长度,短列表对应的字符串排在前面
- 完全基于Java 8的Stream和Lambda表达式实现,符合要求
运行上述代码后,输出结果与期望一致。
内容的提问来源于stack exchange,提问作者Karthikeyan Sankar
相关产品推荐
相关产品推荐

