是否有比较版本号的标准习语?我不能直接使用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
当前回答
下面是一个优化的实现:
public static final Comparator<CharSequence> VERSION_ORDER = new Comparator<CharSequence>() {
@Override
public int compare (CharSequence lhs, CharSequence rhs) {
int ll = lhs.length(), rl = rhs.length(), lv = 0, rv = 0, li = 0, ri = 0;
char c;
do {
lv = rv = 0;
while (--ll >= 0) {
c = lhs.charAt(li++);
if (c < '0' || c > '9')
break;
lv = lv*10 + c - '0';
}
while (--rl >= 0) {
c = rhs.charAt(ri++);
if (c < '0' || c > '9')
break;
rv = rv*10 + c - '0';
}
} while (lv == rv && (ll >= 0 || rl >= 0));
return lv - rv;
}
};
结果:
"0.1" - "1.0" = -1
"1.0" - "1.0" = 0
"1.0" - "1.0.0" = 0
"10" - "1.0" = 9
"3.7.6" - "3.7.11" = -5
"foobar" - "1.0" = -1
其他回答
public int compare(String v1, String v2) {
v1 = v1.replaceAll("\\s", "");
v2 = v2.replaceAll("\\s", "");
String[] a1 = v1.split("\\.");
String[] a2 = v2.split("\\.");
List<String> l1 = Arrays.asList(a1);
List<String> l2 = Arrays.asList(a2);
int i=0;
while(true){
Double d1 = null;
Double d2 = null;
try{
d1 = Double.parseDouble(l1.get(i));
}catch(IndexOutOfBoundsException e){
}
try{
d2 = Double.parseDouble(l2.get(i));
}catch(IndexOutOfBoundsException e){
}
if (d1 != null && d2 != null) {
if (d1.doubleValue() > d2.doubleValue()) {
return 1;
} else if (d1.doubleValue() < d2.doubleValue()) {
return -1;
}
} else if (d2 == null && d1 != null) {
if (d1.doubleValue() > 0) {
return 1;
}
} else if (d1 == null && d2 != null) {
if (d2.doubleValue() > 0) {
return -1;
}
} else {
break;
}
i++;
}
return 0;
}
对于要显示基于版本号的强制更新警报的人,我有以下想法。这可能用于比较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
@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
也许有人会对我的解决方案感兴趣:
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
这篇旧文章的另一个解决方案(对那些可能有帮助的人来说):
public class Version implements Comparable<Version> {
private String version;
public final String get() {
return this.version;
}
public Version(String version) {
if(version == null)
throw new IllegalArgumentException("Version can not be null");
if(!version.matches("[0-9]+(\\.[0-9]+)*"))
throw new IllegalArgumentException("Invalid version format");
this.version = version;
}
@Override public int compareTo(Version that) {
if(that == null)
return 1;
String[] thisParts = this.get().split("\\.");
String[] thatParts = that.get().split("\\.");
int length = Math.max(thisParts.length, thatParts.length);
for(int i = 0; i < length; i++) {
int thisPart = i < thisParts.length ?
Integer.parseInt(thisParts[i]) : 0;
int thatPart = i < thatParts.length ?
Integer.parseInt(thatParts[i]) : 0;
if(thisPart < thatPart)
return -1;
if(thisPart > thatPart)
return 1;
}
return 0;
}
@Override public boolean equals(Object that) {
if(this == that)
return true;
if(that == null)
return false;
if(this.getClass() != that.getClass())
return false;
return this.compareTo((Version) that) == 0;
}
}
Version a = new Version("1.1");
Version b = new Version("1.1.1");
a.compareTo(b) // return -1 (a<b)
a.equals(b) // return false
Version a = new Version("2.0");
Version b = new Version("1.9.9");
a.compareTo(b) // return 1 (a>b)
a.equals(b) // return false
Version a = new Version("1.0");
Version b = new Version("1");
a.compareTo(b) // return 0 (a=b)
a.equals(b) // return true
Version a = new Version("1");
Version b = null;
a.compareTo(b) // return 1 (a>b)
a.equals(b) // return false
List<Version> versions = new ArrayList<Version>();
versions.add(new Version("2"));
versions.add(new Version("1.0.5"));
versions.add(new Version("1.01.0"));
versions.add(new Version("1.00.1"));
Collections.min(versions).get() // return min version
Collections.max(versions).get() // return max version
// WARNING
Version a = new Version("2.06");
Version b = new Version("2.060");
a.equals(b) // return false
编辑:
@daiscog:谢谢你的评论,这段代码是为Android平台开发的,由谷歌推荐,方法“匹配”检查整个字符串,不像Java使用监管模式。(Android文档- JAVA文档)