是否有比较版本号的标准习语?我不能直接使用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
当前回答
如果你的项目中已经有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);
}
}
其他回答
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”的情况下,它仍然不够。
/**
* written by: Stan Towianski - May 2018
* notes: I make assumption each of 3 version sections a.b.c is not longer then 4 digits: aaaa.bbbb.cccc-MODWORD1(-)modnum2
* 5.10.13-release-1 becomes 0000500100013.501 6.0-snapshot becomes 0000600000000.100
* MODWORD1 = -xyz/NotMatching, -SNAPSHOT, -ALPHA, -BETA, -RC, -RELEASE/nothing return: .0, .1, .2, .3, .4, .5
* modnum2 = up to 2 digit/chars second version
* */
public class VersionCk {
private static boolean isVersionHigher( String baseVersion, String testVersion )
{
System.out.println( "versionToComparable( baseVersion ) =" + versionToComparable( baseVersion ) );
System.out.println( "versionToComparable( testVersion ) =" + versionToComparable( testVersion ) + " is this higher ?" );
return versionToComparable( testVersion ).compareTo( versionToComparable( baseVersion ) ) > 0;
}
//---- not worrying about += for something so small
private static String versionToComparable( String version )
{
// System.out.println("version - " + version);
String versionNum = version;
int at = version.indexOf( '-' );
if ( at >= 0 )
versionNum = version.substring( 0, at );
String[] numAr = versionNum.split( "\\." );
String versionFormatted = "0";
for ( String tmp : numAr )
{
versionFormatted += String.format( "%4s", tmp ).replace(' ', '0');
}
while ( versionFormatted.length() < 12 ) // pad out to aaaa.bbbb.cccc
{
versionFormatted += "0000";
}
// System.out.println( "converted min version =" + versionFormatted + "= : " + versionNum );
return versionFormatted + getVersionModifier( version, at );
}
//---- use order low to high: -xyz, -SNAPSHOT, -ALPHA, -BETA, -RC, -RELEASE/nothing returns: 0, 1, 2, 3, 4, 5
private static String getVersionModifier( String version, int at )
{
// System.out.println("version - " + version );
String[] wordModsAr = { "-SNAPSHOT", "-ALPHA", "-BETA", "-RC", "-RELEASE" };
if ( at < 0 )
return "." + wordModsAr.length + "00"; // make nothing = RELEASE level
int i = 1;
for ( String word : wordModsAr )
{
if ( ( at = version.toUpperCase().indexOf( word ) ) > 0 )
return "." + i + getSecondVersionModifier( version.substring( at + word.length() ) );
i++;
}
return ".000";
}
//---- add 2 chars for any number after first modifier. -rc2 or -rc-2 returns 02
private static String getSecondVersionModifier( String version )
{
System.out.println( "second modifier =" + version + "=" );
Matcher m = Pattern.compile("(.*?)(\\d+).*").matcher( version );
// if ( m.matches() )
// System.out.println( "match ? =" + m.matches() + "= m.group(1) =" + m.group(1) + "= m.group(2) =" + m.group(2) + "= m.group(3) =" + (m.groupCount() >= 3 ? m.group(3) : "x") );
// else
// System.out.println( "No match" );
return m.matches() ? String.format( "%2s", m.group(2) ).replace(' ', '0') : "00";
}
public static void main(String[] args)
{
checkVersion( "3.10.0", "3.4.0");
checkVersion( "5.4.2", "5.4.1");
checkVersion( "5.4.4", "5.4.5");
checkVersion( "5.4.9", "5.4.12");
checkVersion( "5.9.222", "5.10.12");
checkVersion( "5.10.12", "5.10.12");
checkVersion( "5.10.13", "5.10.14");
checkVersion( "6.7.0", "6.8");
checkVersion( "6.7", "2.7.0");
checkVersion( "6", "6.3.1");
checkVersion( "4", "4.0.0");
checkVersion( "6.3.0", "6");
checkVersion( "5.10.12-Alpha", "5.10.12-beTA");
checkVersion( "5.10.13-release", "5.10.14-beta");
checkVersion( "6.7.0", "6.8-snapshot");
checkVersion( "6.7.1", "6.7.0-release");
checkVersion( "6-snapshot", "6.0.0-beta");
checkVersion( "6.0-snapshot", "6.0.0-whatthe");
checkVersion( "5.10.12-Alpha-1", "5.10.12-alpha-2");
checkVersion( "5.10.13-release-1", "5.10.13-release2");
checkVersion( "10-rc42", "10.0.0-rc53");
}
private static void checkVersion(String baseVersion, String testVersion)
{
System.out.println( "baseVersion - " + baseVersion );
System.out.println( "testVersion - " + testVersion );
System.out.println( "isVersionHigher = " + isVersionHigher( baseVersion, testVersion ) );
System.out.println( "---------------");
}
}
一些输出:
---------------
baseVersion - 6.7
testVersion - 2.7.0
versionToComparable( baseVersion ) =0000600070000.500
versionToComparable( testVersion ) =0000200070000.500 is this higher ?
isVersionHigher = false
---------------
baseVersion - 6
testVersion - 6.3.1
versionToComparable( baseVersion ) =0000600000000.500
versionToComparable( testVersion ) =0000600030001.500 is this higher ?
isVersionHigher = true
---------------
baseVersion - 4
testVersion - 4.0.0
versionToComparable( baseVersion ) =0000400000000.500
versionToComparable( testVersion ) =0000400000000.500 is this higher ?
isVersionHigher = false
---------------
baseVersion - 6.3.0
testVersion - 6
versionToComparable( baseVersion ) =0000600030000.500
versionToComparable( testVersion ) =0000600000000.500 is this higher ?
isVersionHigher = false
---------------
baseVersion - 5.10.12-Alpha
testVersion - 5.10.12-beTA
second modifier ==
versionToComparable( baseVersion ) =0000500100012.200
second modifier ==
versionToComparable( testVersion ) =0000500100012.300 is this higher ?
second modifier ==
second modifier ==
isVersionHigher = true
---------------
baseVersion - 5.10.13-release
testVersion - 5.10.14-beta
second modifier ==
versionToComparable( baseVersion ) =0000500100013.500
second modifier ==
versionToComparable( testVersion ) =0000500100014.300 is this higher ?
second modifier ==
second modifier ==
isVersionHigher = true
---------------
baseVersion - 6.7.0
testVersion - 6.8-snapshot
versionToComparable( baseVersion ) =0000600070000.500
second modifier ==
versionToComparable( testVersion ) =0000600080000.100 is this higher ?
second modifier ==
isVersionHigher = true
---------------
baseVersion - 6.7.1
testVersion - 6.7.0-release
versionToComparable( baseVersion ) =0000600070001.500
second modifier ==
versionToComparable( testVersion ) =0000600070000.500 is this higher ?
second modifier ==
isVersionHigher = false
---------------
baseVersion - 6-snapshot
testVersion - 6.0.0-beta
second modifier ==
versionToComparable( baseVersion ) =0000600000000.100
second modifier ==
versionToComparable( testVersion ) =0000600000000.300 is this higher ?
second modifier ==
second modifier ==
isVersionHigher = true
---------------
baseVersion - 6.0-snapshot
testVersion - 6.0.0-whatthe
second modifier ==
versionToComparable( baseVersion ) =0000600000000.100
versionToComparable( testVersion ) =0000600000000.000 is this higher ?
second modifier ==
isVersionHigher = false
---------------
baseVersion - 5.10.12-Alpha-1
testVersion - 5.10.12-alpha-2
second modifier =-1=
versionToComparable( baseVersion ) =0000500100012.201
second modifier =-2=
versionToComparable( testVersion ) =0000500100012.202 is this higher ?
second modifier =-2=
second modifier =-1=
isVersionHigher = true
---------------
baseVersion - 5.10.13-release-1
testVersion - 5.10.13-release2
second modifier =-1=
versionToComparable( baseVersion ) =0000500100013.501
second modifier =2=
versionToComparable( testVersion ) =0000500100013.502 is this higher ?
second modifier =2=
second modifier =-1=
isVersionHigher = true
---------------
baseVersion - 10-rc42
testVersion - 10.0.0-rc53
second modifier =42=
versionToComparable( baseVersion ) =0001000000000.442
second modifier =53=
versionToComparable( testVersion ) =0001000000000.453 is this higher ?
second modifier =53=
second modifier =42=
isVersionHigher = true
---------------
public static void main(String[] args) {
String version1 = "1.0";
String version2 = "1.0.0";
String[] version1_splits = version1.split("\\.");
String[] version2_splits = version2.split("\\.");
int length = version1_splits.length >= version2_splits.length ? version1_splits.length : version2_splits.length;
int i=0;
for(;i<length;i++){
int version1_int = getValue(version1_splits,i);
int version2_int = getValue(version2_splits,i);
if(version1_int > version2_int){
System.out.println("version1 > version2");
break;
}
else if(version1_int < version2_int){
System.out.println("version2 > version1");
break;
}
else{
if(i == length-1)
System.out.println("version1 = version2");
}
}
}
private static int getValue(String[] version1_splits, int i) {
int temp;
try{
temp = Integer.valueOf(version1_splits[i]);
}
catch(IndexOutOfBoundsException e){
temp=0;
}
return temp;
}
想知道为什么每个人都假设版本只由整数组成-在我的情况下,它不是。
为什么要重新发明轮子(假设版本遵循Semver标准)
首先通过Maven安装https://github.com/vdurmont/semver4j
然后使用这个库
Semver sem = new Semver("1.2.3");
sem.isGreaterThan("1.2.2"); // true