Java实现字符串数组存储的语义化版本号排序及问题解决
语义化版本字符串数组升序排序实现
现有代码的核心问题
- 排序逻辑缺失多轮迭代:原代码仅执行1轮相邻元素遍历,本质是不完整的冒泡排序——没有多轮将当前未排序区间的最大值逐步交换到区间尾部的过程,无法让所有元素落到正确位置。比如输入数组里的
0.0.0位于下标3,单轮遍历最多只能完成有限次数的相邻交换,根本到不了数组头部的目标位置。 - 版本比较逻辑存在缺陷:原代码仅以第一个被比较版本的分段长度作为循环上限,一方面会在访问更短的分段数组时触发数组越界,另一方面也没法实现“缺失的分段默认补0”的语义化版本比较规则。
- 逻辑耦合度过高:版本拆分、大小比较、数组元素交换的逻辑全部揉在单层循环里,没法独立复用版本比较规则,也没法借助Java内置的高性能排序工具简化代码。
正确实现思路
1. 抽取独立的版本比较方法
先把“两个语义化版本的大小比较”的逻辑抽出来,逐段拆分后转成整数比对,只要某一段分出大小就直接返回比较结果,所有分段相等则判定为同版本:
/** * 比较两个语义化版本的大小 * @return 正数表示v1 > v2,负数表示v1 < v2,0表示版本相等 */ private static int compareSemanticVersion(String v1, String v2) { String[] v1Parts = v1.split("\\."); String[] v2Parts = v2.split("\\."); // 以两个版本的最大分段长度为循环上限,缺省位置补0 int maxPartLen = Math.max(v1Parts.length, v2Parts.length); for (int i = 0; i < maxPartLen; i++) { int num1 = i < v1Parts.length ? Integer.parseInt(v1Parts[i]) : 0; int num2 = i < v2Parts.length ? Integer.parseInt(v2Parts[i]) : 0; if (num1 != num2) { return num1 - num2; } } return 0; }
2. 选择排序实现方式
方案1:使用Java内置排序工具(推荐)
直接把上面写好的比较逻辑传给Arrays.sort()即可,性能远高于手写裸循环,代码也更简洁:
import java.util.Arrays; public static String[] sortVersions(String[] versionArray) { // 拷贝原数组避免修改入参,可根据需求直接修改原数组 String[] sortedArray = Arrays.copyOf(versionArray, versionArray.length); Arrays.sort(sortedArray, (v1, v2) -> compareSemanticVersion(v1, v2)); return sortedArray; }
使用题目给出的测试输入运行后,输出结果完全匹配预期:{0.0.0, 1.0.0, 1.0.1, 1.1.2, 2.3.4, 12.2.1, 12.2.2, 13.2.4}。
方案2:修正原手写冒泡排序代码
如果要保留手写排序的实现,只需要在原基础上补全双层冒泡的循环结构,把比较判断替换成上面抽取的独立方法即可:
public static String[] compare(String[] a) { String temp; // 外层循环控制冒泡轮数 for (int i = 0; i < a.length - 1; i++) { // 内层循环遍历未排序区间,做相邻元素交换 for (int j = 0; j < a.length - 1 - i; j++) { if (compareSemanticVersion(a[j], a[j + 1]) > 0) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } return a; }
绝对不能直接用字符串字典序做版本比较,比如
"13.2.4"和"2.3.4"做字典序比对时,因为首字符'1'的ASCII码小于'2',会错误判定13.2.4 < 2.3.4,完全违背语义化版本的数值比较规则。
内容的提问来源于stack exchange,提问作者henil shah
相关产品推荐
相关产品推荐

