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

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.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。

您需要规范化版本字符串,以便对它们进行比较。类似的

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'

我喜欢@Peter Lawrey的想法,我把它扩展到更远的范围:

    /**
    * Normalize string array, 
    * Appends zeros if string from the array
    * has length smaller than the maxLen.
    **/
    private String normalize(String[] split, int maxLen){
        StringBuilder sb = new StringBuilder("");
        for(String s : split) {
            for(int i = 0; i<maxLen-s.length(); i++) sb.append('0');
            sb.append(s);
        }
        return sb.toString();
    }

    /**
    * Removes trailing zeros of the form '.00.0...00'
    * (and does not remove zeros from, say, '4.1.100')
    **/
    public String removeTrailingZeros(String s){
        int i = s.length()-1;
        int k = s.length()-1;
        while(i >= 0 && (s.charAt(i) == '.' || s.charAt(i) == '0')){
          if(s.charAt(i) == '.') k = i-1;
          i--;  
        } 
        return s.substring(0,k+1);
    }

    /**
    * Compares two versions(works for alphabets too),
    * Returns 1 if v1 > v2, returns 0 if v1 == v2,
    * and returns -1 if v1 < v2.
    **/
    public int compareVersion(String v1, String v2) {

        // Uncomment below two lines if for you, say, 4.1.0 is equal to 4.1
        // v1 = removeTrailingZeros(v1);
        // v2 = removeTrailingZeros(v2);

        String[] splitv1 = v1.split("\\.");
        String[] splitv2 = v2.split("\\.");
        int maxLen = 0;
        for(String str : splitv1) maxLen = Math.max(maxLen, str.length());
        for(String str : splitv2) maxLen = Math.max(maxLen, str.length());
        int cmp = normalize(splitv1, maxLen).compareTo(normalize(splitv2, maxLen));
        return cmp > 0 ? 1 : (cmp < 0 ? -1 : 0);
    }

希望它能帮助到别人。它通过了interviewbit和leetcode中的所有测试用例(需要取消compareVersion函数中的两行注释)。

很容易测试!

我写了一个名为MgntUtils的开源库,它有一个用于字符串版本的实用程序。它正确地比较它们,适用于版本范围等等。下面是这个库javadoc参见方法TextUtils.comapreVersions(…)它已经被大量使用并经过了良好的测试。下面这篇文章描述了这个库以及如何获取它。它可以作为Maven工件和在github上获得(包括源代码和JavaDoc)