是否有比较版本号的标准习语?我不能直接使用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
当前回答
我写了一个小的Java/Android库来比较版本号:https://github.com/G00fY2/version-compare
它的基本功能是:
public int compareVersions(String versionA, String versionB) {
String[] versionTokensA = versionA.split("\\.");
String[] versionTokensB = versionB.split("\\.");
List<Integer> versionNumbersA = new ArrayList<>();
List<Integer> versionNumbersB = new ArrayList<>();
for (String versionToken : versionTokensA) {
versionNumbersA.add(Integer.parseInt(versionToken));
}
for (String versionToken : versionTokensB) {
versionNumbersB.add(Integer.parseInt(versionToken));
}
final int versionASize = versionNumbersA.size();
final int versionBSize = versionNumbersB.size();
int maxSize = Math.max(versionASize, versionBSize);
for (int i = 0; i < maxSize; i++) {
if ((i < versionASize ? versionNumbersA.get(i) : 0) > (i < versionBSize ? versionNumbersB.get(i) : 0)) {
return 1;
} else if ((i < versionASize ? versionNumbersA.get(i) : 0) < (i < versionBSize ? versionNumbersB.get(i) : 0)) {
return -1;
}
}
return 0;
}
这个代码片段不提供任何错误检查或处理。除此之外,我的库还支持像“1.2-rc”>“1.2-beta”这样的后缀。
其他回答
我自己写了一个小函数。更简单地使用列表
public static boolean checkVersionUpdate(String olderVerison, String newVersion) {
if (olderVerison.length() == 0 || newVersion.length() == 0) {
return false;
}
List<String> newVerList = Arrays.asList(newVersion.split("\\."));
List<String> oldVerList = Arrays.asList(olderVerison.split("\\."));
int diff = newVerList.size() - oldVerList.size();
List<String> newList = new ArrayList<>();
if (diff > 0) {
newList.addAll(oldVerList);
for (int i = 0; i < diff; i++) {
newList.add("0");
}
return examineArray(newList, newVerList, diff);
} else if (diff < 0) {
newList.addAll(newVerList);
for (int i = 0; i < -diff; i++) {
newList.add("0");
}
return examineArray(oldVerList, newList, diff);
} else {
return examineArray(oldVerList, newVerList, diff);
}
}
public static boolean examineArray(List<String> oldList, List<String> newList, int diff) {
boolean newVersionGreater = false;
for (int i = 0; i < oldList.size(); i++) {
if (Integer.parseInt(newList.get(i)) > Integer.parseInt(oldList.get(i))) {
newVersionGreater = true;
break;
} else if (Integer.parseInt(newList.get(i)) < Integer.parseInt(oldList.get(i))) {
newVersionGreater = false;
break;
} else {
newVersionGreater = diff > 0;
}
}
return newVersionGreater;
}
public static int compareVersions(String version1, String version2){
String[] levels1 = version1.split("\\.");
String[] levels2 = version2.split("\\.");
int length = Math.max(levels1.length, levels2.length);
for (int i = 0; i < length; i++){
Integer v1 = i < levels1.length ? Integer.parseInt(levels1[i]) : 0;
Integer v2 = i < levels2.length ? Integer.parseInt(levels2[i]) : 0;
int compare = v1.compareTo(v2);
if (compare != 0){
return compare;
}
}
return 0;
}
由于本页上没有答案能很好地处理混合文本,我做了自己的版本:
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”的情况下,它仍然不够。
使用Maven真的很简单:
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
DefaultArtifactVersion minVersion = new DefaultArtifactVersion("1.0.1");
DefaultArtifactVersion maxVersion = new DefaultArtifactVersion("1.10");
DefaultArtifactVersion version = new DefaultArtifactVersion("1.11");
if (version.compareTo(minVersion) < 0 || version.compareTo(maxVersion) > 0) {
System.out.println("Sorry, your version is unsupported");
}
您可以从这个页面获得Maven Artifact的正确依赖项字符串:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.0.3</version>
</dependency>
也许有人会对我的解决方案感兴趣:
class Version private constructor(private val versionString: String) : Comparable<Version> {
private val major: Int by lazy { versionString.split(".")[0].toInt() }
private val minor: Int by lazy { versionString.split(".")[1].toInt() }
private val patch: Int by lazy {
val splitArray = versionString.split(".")
if (splitArray.size == 3)
splitArray[2].toInt()
else
0
}
override fun compareTo(other: Version): Int {
return when {
major > other.major -> 1
major < other.major -> -1
minor > other.minor -> 1
minor < other.minor -> -1
patch > other.patch -> 1
patch < other.patch -> -1
else -> 0
}
}
override fun equals(other: Any?): Boolean {
if (other == null || other !is Version) return false
return compareTo(other) == 0
}
override fun hashCode(): Int {
return major * minor * patch
}
companion object {
private fun doesContainsVersion(string: String): Boolean {
val versionArray = string.split(".")
return versionArray.size in 2..3
&& versionArray[0].toIntOrNull() != null
&& versionArray[1].toIntOrNull() != null
&& (versionArray.size == 2 || versionArray[2].toIntOrNull() != null)
}
fun from(string: String): Version? {
return if (doesContainsVersion(string)) {
Version(string)
} else {
null
}
}
}
}
用法:
val version1 = Version.from("3.2")
val version2 = Version.from("3.2.1")
version1 <= version2