是否有比较版本号的标准习语?我不能直接使用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;
}
其他回答
您需要规范化版本字符串,以便对它们进行比较。类似的
import java.util.regex.Pattern;
public class Main {
public static void main(String... args) {
compare("1.0", "1.1");
compare("1.0.1", "1.1");
compare("1.9", "1.10");
compare("1.a", "1.9");
}
private static void compare(String v1, String v2) {
String s1 = normalisedVersion(v1);
String s2 = normalisedVersion(v2);
int cmp = s1.compareTo(s2);
String cmpStr = cmp < 0 ? "<" : cmp > 0 ? ">" : "==";
System.out.printf("'%s' %s '%s'%n", v1, cmpStr, v2);
}
public static String normalisedVersion(String version) {
return normalisedVersion(version, ".", 4);
}
public static String normalisedVersion(String version, String sep, int maxWidth) {
String[] split = Pattern.compile(sep, Pattern.LITERAL).split(version);
StringBuilder sb = new StringBuilder();
for (String s : split) {
sb.append(String.format("%" + maxWidth + 's', s));
}
return sb.toString();
}
}
打印
'1.0' < '1.1' '1.0.1' < '1.1' '1.9' < '1.10' “1。A ' > '1.9'
由于本页上没有答案能很好地处理混合文本,我做了自己的版本:
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>
如果你的项目中已经有Jackson,你可以使用com.fasterxml.jackson.core.Version:
import com.fasterxml.jackson.core.Version;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class VersionTest {
@Test
public void shouldCompareVersion() {
Version version1 = new Version(1, 11, 1, null, null, null);
Version version2 = new Version(1, 12, 1, null, null, null);
assertTrue(version1.compareTo(version2) < 0);
}
}
此代码尝试解决这种类型的比较版本。
大多数版本说明符,如>= 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;
}