是否有比较版本号的标准习语?我不能直接使用String compareTo,因为我还不知道点释放的最大数量是多少。我需要比较版本,并有以下保持正确:
1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10
是否有比较版本号的标准习语?我不能直接使用String compareTo,因为我还不知道点释放的最大数量是多少。我需要比较版本,并有以下保持正确:
1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10
当前回答
对于我的项目,我使用我的公共版本库https://github.com/raydac/commons-version 它包含两个辅助类-用于解析版本(解析后的版本可以与另一个版本对象进行比较,因为它是可比的)和VersionValidator,它允许检查一些表达式的版本,如!=ide-1.1.1,>idea-1.3.4-SNAPSHOT;<1.2.3
其他回答
我创建了一个简单的实用程序,使用语义版本约定在Android平台上比较版本。所以它只适用于X.Y.Z (Major.Minor.Patch)格式的字符串,其中X、Y和Z是非负整数。你可以在我的GitHub上找到它。
方法version . compareversions (String v1, String v2)比较两个版本字符串。如果版本相等则返回0,如果版本v1在版本v2之前则返回1,如果版本v1在版本v2之后则返回-1,如果版本格式无效则返回-2。
public class VersionComparator {
/* loop through both version strings
* then loop through the inner string to computer the val of the int
* for each integer read, do num*10+<integer read>
* and stop when stumbling upon '.'
* When '.' is encountered...
* see if '.' is encountered for both strings
* if it is then compare num1 and num2
* if num1 == num2... iterate over p1++, p2++
* else return (num1 > num2) ? 1 : -1
* If both the string end then compare(num1, num2) return 0, 1, -1
* else loop through the longer string and
* verify if it only has trailing zeros
* If it only has trailing zeros then return 0
* else it is greater than the other string
*/
public static int compareVersions(String v1, String v2) {
int num1 = 0;
int num2 = 0;
int p1 = 0;
int p2 = 0;
while (p1 < v1.length() && p2 < v2.length()) {
num1 = Integer.parseInt(v1.charAt(p1) + "");
num2 = Integer.parseInt(v2.charAt(p2) + "");
p1++;
p2++;
while (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) != '.' && v2.charAt(p2) != '.') {
if (p1 < v1.length()) num1 = num1 * 10 + Integer.parseInt(v1.charAt(p1) + "");
if (p2 < v2.length()) num2 = num2 * 10 + Integer.parseInt(v2.charAt(p2) + "");
p1++;
p2++;
}
if (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) == '.' && v2.charAt(p2) == '.') {
if ((num1 ^ num2) == 0) {
p1++;
p2++;
}
else return (num1 > num2) ? 1 : -1;
}
else if (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) == '.') return -1;
else if (p1 < v1.length() && p2 < v2.length() && v2.charAt(p2) == '.') return 1;
}
if (p1 == v1.length() && p2 == v2.length()) {
if ((num1 ^ num2) == 0) return 0;
else return (num1 > num2) ? 1 : -1;
}
else if (p1 == v1.length()) {
if ((num1 ^ num2) == 0) {
while (p2 < v2.length()) {
if (v2.charAt(p2) != '.' && v2.charAt(p2) != '0') return -1;
p2++;
}
return 0;
}
else return (num1 > num2) ? 1 : -1;
}
else {
if ((num1 ^ num2) == 0) {
while (p1 < v1.length()) {
if (v1.charAt(p1) != '.' && v1.charAt(p1) != '0') return 1;
p1++;
}
return 0;
}
else return (num1 > num2) ? 1 : -1;
}
}
public static void main(String[] args) {
System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
System.out.println(compareVersions("11.21.1.0.0.1.0", "11.23") ^ -1);
System.out.println(compareVersions("11.23", "11.23.0.0.0.1.0") ^ -1);
System.out.println(compareVersions("11.2", "11.23") ^ -1);
System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
System.out.println(compareVersions("1.21.1.0.0.1.0", "2.23") ^ -1);
System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
System.out.println(compareVersions("11.23.0.0.0.0.0", "11.23") ^ 0);
System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
System.out.println(compareVersions("1.5.1.3", "1.5.1.3.0") ^ 0);
System.out.println(compareVersions("1.5.1.4", "1.5.1.3.0") ^ 1);
System.out.println(compareVersions("1.2.1.3", "1.5.1.3.0") ^ -1);
System.out.println(compareVersions("1.2.1.3", "1.22.1.3.0") ^ -1);
System.out.println(compareVersions("1.222.1.3", "1.22.1.3.0") ^ 1);
}
}
由于本页上没有答案能很好地处理混合文本,我做了自己的版本:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Main {
static double parseVersion(String v) {
if (v.isEmpty()) {
return 0;
}
Pattern p = Pattern.compile("^(\\D*)(\\d*)(\\D*)$");
Matcher m = p.matcher(v);
m.find();
if (m.group(2).isEmpty()) {
// v1.0.0.[preview]
return -1;
}
double i = Integer.parseInt(m.group(2));
if (!m.group(3).isEmpty()) {
// v1.0.[0b]
i -= 0.1;
}
return i;
}
public static int versionCompare(String str1, String str2) {
String[] v1 = str1.split("\\.");
String[] v2 = str2.split("\\.");
int i = 0;
for (; i < v1.length && i < v2.length; i++) {
double iv1 = parseVersion(v1[i]);
double iv2 = parseVersion(v2[i]);
if (iv1 != iv2) {
return iv1 - iv2 < 0 ? -1 : 1;
}
}
if (i < v1.length) {
// "1.0.1", "1.0"
double iv1 = parseVersion(v1[i]);
return iv1 < 0 ? -1 : (int) Math.ceil(iv1);
}
if (i < v2.length) {
double iv2 = parseVersion(v2[i]);
return -iv2 < 0 ? -1 : (int) Math.ceil(iv2);
}
return 0;
}
public static void main(String[] args) {
System.out.println("versionCompare(v1.0.0, 1.0.0)");
System.out.println(versionCompare("v1.0.0", "1.0.0")); // 0
System.out.println("versionCompare(v1.0.0b, 1.0.0)");
System.out.println(versionCompare("v1.0.0b", "1.0.0")); // -1
System.out.println("versionCompare(v1.0.0.preview, 1.0.0)");
System.out.println(versionCompare("v1.0.0.preview", "1.0.0")); // -1
System.out.println("versionCompare(v1.0, 1.0.0)");
System.out.println(versionCompare("v1.0", "1.0.0")); // 0
System.out.println("versionCompare(ver1.0, 1.0.1)");
System.out.println(versionCompare("ver1.0", "1.0.1")); // -1
}
}
不过,在需要比较“alpha”和“beta”的情况下,它仍然不够。
对于我的项目,我使用我的公共版本库https://github.com/raydac/commons-version 它包含两个辅助类-用于解析版本(解析后的版本可以与另一个版本对象进行比较,因为它是可比的)和VersionValidator,它允许检查一些表达式的版本,如!=ide-1.1.1,>idea-1.3.4-SNAPSHOT;<1.2.3
@alex在Kotlin上的帖子
class Version(inputVersion: String) : Comparable<Version> {
var version: String
private set
override fun compareTo(other: Version) =
(split() to other.split()).let {(thisParts, thatParts)->
val length = max(thisParts.size, thatParts.size)
for (i in 0 until length) {
val thisPart = if (i < thisParts.size) thisParts[i].toInt() else 0
val thatPart = if (i < thatParts.size) thatParts[i].toInt() else 0
if (thisPart < thatPart) return -1
if (thisPart > thatPart) return 1
}
0
}
init {
require(inputVersion.matches("[0-9]+(\\.[0-9]+)*".toRegex())) { "Invalid version format" }
version = inputVersion
}
}
fun Version.split() = version.split(".").toTypedArray()
用法:
Version("1.2.4").compareTo(Version("0.0.5")) //return 1