是否有比较版本号的标准习语?我不能直接使用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
当前回答
我创建了一个简单的实用程序,使用语义版本约定在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。
其他回答
由于本页上没有答案能很好地处理混合文本,我做了自己的版本:
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”的情况下,它仍然不够。
对于要显示基于版本号的强制更新警报的人,我有以下想法。这可能用于比较Android当前应用版本和firebase远程配置版本之间的版本。这并不是问题的确切答案,但这肯定会对某人有所帮助。
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class Main
{
static String firebaseVersion = "2.1.3"; // or 2.1
static String appVersion = "2.1.4";
static List<String> firebaseVersionArray;
static List<String> appVersionArray;
static boolean isNeedToShowAlert = false;
public static void main (String[]args)
{
System.out.println ("Hello World");
firebaseVersionArray = new ArrayList<String>(Arrays.asList(firebaseVersion.split ("\\.")));
appVersionArray = new ArrayList<String>(Arrays.asList(appVersion.split ("\\.")));
if(appVersionArray.size() < firebaseVersionArray.size()) {
appVersionArray.add("0");
}
if(firebaseVersionArray.size() < appVersionArray.size()) {
firebaseVersionArray.add("0");
}
isNeedToShowAlert = needToShowAlert(); //Returns false
System.out.println (isNeedToShowAlert);
}
static boolean needToShowAlert() {
boolean result = false;
for(int i = 0 ; i < appVersionArray.size() ; i++) {
if (Integer.parseInt(appVersionArray.get(i)) == Integer.parseInt(firebaseVersionArray.get(i))) {
continue;
} else if (Integer.parseInt(appVersionArray.get(i)) > Integer.parseInt(firebaseVersionArray.get(i))){
result = false;
break;
} else if (Integer.parseInt(appVersionArray.get(i)) < Integer.parseInt(firebaseVersionArray.get(i))) {
result = true;
break;
}
}
return result;
}
}
您可以通过复制粘贴来运行此代码 https://www.onlinegdb.com/online_java_compiler
用点作为分隔符对字符串进行标记,然后从左边开始并排比较整数转换。
// VersionComparator.java
import java.util.Comparator;
public class VersionComparator implements Comparator {
public boolean equals(Object o1, Object o2) {
return compare(o1, o2) == 0;
}
public int compare(Object o1, Object o2) {
String version1 = (String) o1;
String version2 = (String) o2;
VersionTokenizer tokenizer1 = new VersionTokenizer(version1);
VersionTokenizer tokenizer2 = new VersionTokenizer(version2);
int number1 = 0, number2 = 0;
String suffix1 = "", suffix2 = "";
while (tokenizer1.MoveNext()) {
if (!tokenizer2.MoveNext()) {
do {
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
if (number1 != 0 || suffix1.length() != 0) {
// Version one is longer than number two, and non-zero
return 1;
}
}
while (tokenizer1.MoveNext());
// Version one is longer than version two, but zero
return 0;
}
number1 = tokenizer1.getNumber();
suffix1 = tokenizer1.getSuffix();
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number1 < number2) {
// Number one is less than number two
return -1;
}
if (number1 > number2) {
// Number one is greater than number two
return 1;
}
boolean empty1 = suffix1.length() == 0;
boolean empty2 = suffix2.length() == 0;
if (empty1 && empty2) continue; // No suffixes
if (empty1) return 1; // First suffix is empty (1.2 > 1.2b)
if (empty2) return -1; // Second suffix is empty (1.2a < 1.2)
// Lexical comparison of suffixes
int result = suffix1.compareTo(suffix2);
if (result != 0) return result;
}
if (tokenizer2.MoveNext()) {
do {
number2 = tokenizer2.getNumber();
suffix2 = tokenizer2.getSuffix();
if (number2 != 0 || suffix2.length() != 0) {
// Version one is longer than version two, and non-zero
return -1;
}
}
while (tokenizer2.MoveNext());
// Version two is longer than version one, but zero
return 0;
}
return 0;
}
}
// VersionTokenizer.java
public class VersionTokenizer {
private final String _versionString;
private final int _length;
private int _position;
private int _number;
private String _suffix;
private boolean _hasValue;
public int getNumber() {
return _number;
}
public String getSuffix() {
return _suffix;
}
public boolean hasValue() {
return _hasValue;
}
public VersionTokenizer(String versionString) {
if (versionString == null)
throw new IllegalArgumentException("versionString is null");
_versionString = versionString;
_length = versionString.length();
}
public boolean MoveNext() {
_number = 0;
_suffix = "";
_hasValue = false;
// No more characters
if (_position >= _length)
return false;
_hasValue = true;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c < '0' || c > '9') break;
_number = _number * 10 + (c - '0');
_position++;
}
int suffixStart = _position;
while (_position < _length) {
char c = _versionString.charAt(_position);
if (c == '.') break;
_position++;
}
_suffix = _versionString.substring(suffixStart, _position);
if (_position < _length) _position++;
return true;
}
}
例子:
public class Main
{
private static VersionComparator cmp;
public static void main (String[] args)
{
cmp = new VersionComparator();
Test(new String[]{"1.1.2", "1.2", "1.2.0", "1.2.1", "1.12"});
Test(new String[]{"1.3", "1.3a", "1.3b", "1.3-SNAPSHOT"});
}
private static void Test(String[] versions) {
for (int i = 0; i < versions.length; i++) {
for (int j = i; j < versions.length; j++) {
Test(versions[i], versions[j]);
}
}
}
private static void Test(String v1, String v2) {
int result = cmp.compare(v1, v2);
String op = "==";
if (result < 0) op = "<";
if (result > 0) op = ">";
System.out.printf("%s %s %s\n", v1, op, v2);
}
}
输出:
1.1.2 == 1.1.2 ---> same length and value
1.1.2 < 1.2 ---> first number (1) less than second number (2) => -1
1.1.2 < 1.2.0 ---> first number (1) less than second number (2) => -1
1.1.2 < 1.2.1 ---> first number (1) less than second number (2) => -1
1.1.2 < 1.12 ---> first number (1) less than second number (12) => -1
1.2 == 1.2 ---> same length and value
1.2 == 1.2.0 ---> first shorter than second, but zero
1.2 < 1.2.1 ---> first shorter than second, and non-zero
1.2 < 1.12 ---> first number (2) less than second number (12) => -1
1.2.0 == 1.2.0 ---> same length and value
1.2.0 < 1.2.1 ---> first number (0) less than second number (1) => -1
1.2.0 < 1.12 ---> first number (2) less than second number (12) => -1
1.2.1 == 1.2.1 ---> same length and value
1.2.1 < 1.12 ---> first number (2) less than second number (12) => -1
1.12 == 1.12 ---> same length and value
1.3 == 1.3 ---> same length and value
1.3 > 1.3a ---> first suffix ('') is empty, but not second ('a') => 1
1.3 > 1.3b ---> first suffix ('') is empty, but not second ('b') => 1
1.3 > 1.3-SNAPSHOT ---> first suffix ('') is empty, but not second ('-SNAPSHOT') => 1
1.3a == 1.3a ---> same length and value
1.3a < 1.3b ---> first suffix ('a') compared to second suffix ('b') => -1
1.3a < 1.3-SNAPSHOT ---> first suffix ('a') compared to second suffix ('-SNAPSHOT') => -1
1.3b == 1.3b ---> same length and value
1.3b < 1.3-SNAPSHOT ---> first suffix ('b') compared to second suffix ('-SNAPSHOT') => -1
1.3-SNAPSHOT == 1.3-SNAPSHOT ---> same length and value
我写了一个名为MgntUtils的开源库,它有一个用于字符串版本的实用程序。它正确地比较它们,适用于版本范围等等。下面是这个库javadoc参见方法TextUtils.comapreVersions(…)它已经被大量使用并经过了良好的测试。下面这篇文章描述了这个库以及如何获取它。它可以作为Maven工件和在github上获得(包括源代码和JavaDoc)