是否有比较版本号的标准习语?我不能直接使用String compareTo,因为我还不知道点释放的最大数量是多少。我需要比较版本,并有以下保持正确:

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10

当前回答

也许有人会对我的解决方案感兴趣:

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 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;
}

对于我的项目,我使用我的公共版本库https://github.com/raydac/commons-version 它包含两个辅助类-用于解析版本(解析后的版本可以与另一个版本对象进行比较,因为它是可比的)和VersionValidator,它允许检查一些表达式的版本,如!=ide-1.1.1,>idea-1.3.4-SNAPSHOT;<1.2.3

基于https://stackoverflow.com/a/27891752/2642478

class Version(private val value: String) : Comparable<Version> {
    private val splitted by lazy { value.split("-").first().split(".").map { it.toIntOrNull() ?: 0 } }

    override fun compareTo(other: Version): Int {
        for (i in 0 until maxOf(splitted.size, other.splitted.size)) {
            val compare = splitted.getOrElse(i) { 0 }.compareTo(other.splitted.getOrElse(i) { 0 })
            if (compare != 0)
                return compare
        }
        return 0
    }
}

你可以用like:

    System.err.println(Version("1.0").compareTo( Version("1.0")))
    System.err.println(Version("1.0") < Version("1.1"))
    System.err.println(Version("1.10") > Version("1.9"))
    System.err.println(Version("1.10.1") > Version("1.10"))
    System.err.println(Version("0.0.1") < Version("1"))

这篇旧文章的另一个解决方案(对那些可能有帮助的人来说):

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文档)

/**  
 *  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
---------------