是否有比较版本号的标准习语?我不能直接使用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 8 Stream替换组件中的前导零。这段代码通过了interviewbit.com上的所有测试
public int compareVersion(String A, String B) {
List<String> strList1 = Arrays.stream(A.split("\\."))
.map(s -> s.replaceAll("^0+(?!$)", ""))
.collect(Collectors.toList());
List<String> strList2 = Arrays.stream(B.split("\\."))
.map(s -> s.replaceAll("^0+(?!$)", ""))
.collect(Collectors.toList());
int len1 = strList1.size();
int len2 = strList2.size();
int i = 0;
while(i < len1 && i < len2){
if (strList1.get(i).length() > strList2.get(i).length()) return 1;
if (strList1.get(i).length() < strList2.get(i).length()) return -1;
int result = new Long(strList1.get(i)).compareTo(new Long(strList2.get(i)));
if (result != 0) return result;
i++;
}
while (i < len1){
if (!strList1.get(i++).equals("0")) return 1;
}
while (i < len2){
if (!strList2.get(i++).equals("0")) return -1;
}
return 0;
}
其他回答
使用Java 9自带的Version类
import java.util.*;
import java.lang.module.ModuleDescriptor.Version;
class Main {
public static void main(String[] args) {
var versions = Arrays.asList(
"1.0.2",
"1.0.0-beta.2",
"1.0.0",
"1.0.0-beta",
"1.0.0-alpha.12",
"1.0.0-beta.11",
"1.0.1",
"1.0.11",
"1.0.0-rc.1",
"1.0.0-alpha.1",
"1.1.0",
"1.0.0-alpha.beta",
"1.11.0",
"1.0.0-alpha.12.ab-c",
"0.0.1",
"1.2.1",
"1.0.0-alpha",
"1.0.0.1", // Also works with a number of sections different than 3
"1.0.0.2",
"2",
"10",
"1.0.0.10"
);
versions.stream()
.map(Version::parse)
.sorted()
.forEach(System.out::println);
}
}
在网上试试!
输出:
0.0.1
1.0.0-alpha
1.0.0-alpha.1
1.0.0-alpha.12
1.0.0-alpha.12.ab-c
1.0.0-alpha.beta
1.0.0-beta
1.0.0-beta.2
1.0.0-beta.11
1.0.0-rc.1
1.0.0
1.0.0.1
1.0.0.2
1.0.0.10
1.0.1
1.0.2
1.0.11
1.1.0
1.2.1
1.11.0
2
10
这篇旧文章的另一个解决方案(对那些可能有帮助的人来说):
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文档)
我创建了一个简单的实用程序,使用语义版本约定在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 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;
}
此代码尝试解决这种类型的比较版本。
大多数版本说明符,如>= 1.0,都是不言自明的。的 说明符~>具有特殊含义,最好通过示例来说明。~> 2.0.3是 与>= 2.0.3和< 2.1相同。~> 2.1与>= 2.1相同,且< 3.0.
public static boolean apply(String cmpDeviceVersion, String reqDeviceVersion)
{
Boolean equal = !cmpDeviceVersion.contains(">") && !cmpDeviceVersion.contains(">=") &&
!cmpDeviceVersion.contains("<") && !cmpDeviceVersion.contains("<=") &&
!cmpDeviceVersion.contains("~>");
Boolean between = cmpDeviceVersion.contains("~>");
Boolean higher = cmpDeviceVersion.contains(">") && !cmpDeviceVersion.contains(">=") && !cmpDeviceVersion.contains("~>");
Boolean higherOrEqual = cmpDeviceVersion.contains(">=");
Boolean less = cmpDeviceVersion.contains("<") && !cmpDeviceVersion.contains("<=");
Boolean lessOrEqual = cmpDeviceVersion.contains("<=");
cmpDeviceVersion = cmpDeviceVersion.replaceAll("[<>=~]", "");
cmpDeviceVersion = cmpDeviceVersion.trim();
String[] version = cmpDeviceVersion.split("\\.");
String[] reqVersion = reqDeviceVersion.split("\\.");
if(equal)
{
return isEqual(version, reqVersion);
}
else if(between)
{
return isBetween(version, reqVersion);
}
else if(higher)
{
return isHigher(version, reqVersion);
}
else if(higherOrEqual)
{
return isEqual(version, reqVersion) || isHigher(version, reqVersion);
}
else if(less)
{
return isLess(version, reqVersion);
}
else if(lessOrEqual)
{
return isEqual(version, reqVersion) || isLess(version, reqVersion);
}
return false;
}
private static boolean isEqual(String[] version, String[] reqVersion)
{
String strVersion = StringUtils.join(version);
String strReqVersion = StringUtils.join(reqVersion);
if(version.length > reqVersion.length)
{
Integer diff = version.length - reqVersion.length;
strReqVersion += StringUtils.repeat(".0", diff);
}
else if(reqVersion.length > version.length)
{
Integer diff = reqVersion.length - version.length;
strVersion += StringUtils.repeat(".0", diff);
}
return strVersion.equals(strReqVersion);
}
private static boolean isHigher(String[] version, String[] reqVersion)
{
String strVersion = StringUtils.join(version);
String strReqVersion = StringUtils.join(reqVersion);
if(version.length > reqVersion.length)
{
Integer diff = version.length - reqVersion.length;
strReqVersion += StringUtils.repeat(".0", diff);
}
else if(reqVersion.length > version.length)
{
Integer diff = reqVersion.length - version.length;
strVersion += StringUtils.repeat(".0", diff);
}
return strReqVersion.compareTo(strVersion) > 0;
}
private static boolean isLess(String[] version, String[] reqVersion)
{
String strVersion = StringUtils.join(version);
String strReqVersion = StringUtils.join(reqVersion);
if(version.length > reqVersion.length)
{
Integer diff = version.length - reqVersion.length;
strReqVersion += StringUtils.repeat(".0", diff);
}
else if(reqVersion.length > version.length)
{
Integer diff = reqVersion.length - version.length;
strVersion += StringUtils.repeat(".0", diff);
}
return strReqVersion.compareTo(strVersion) < 0;
}
private static boolean isBetween(String[] version, String[] reqVersion)
{
return (isEqual(version, reqVersion) || isHigher(version, reqVersion)) &&
isLess(getNextVersion(version), reqVersion);
}
private static String[] getNextVersion(String[] version)
{
String[] nextVersion = new String[version.length];
for(int i = version.length - 1; i >= 0 ; i--)
{
if(i == version.length - 1)
{
nextVersion[i] = "0";
}
else if((i == version.length - 2) && NumberUtils.isNumber(version[i]))
{
nextVersion[i] = String.valueOf(NumberUtils.toInt(version[i]) + 1);
}
else
{
nextVersion[i] = version[i];
}
}
return nextVersion;
}