String.compareTo()方法用于版本号比较的坑

  最近项目中需要比较客户端版本,项目之初使用String.compareTo()方法进行版本比较,客户端版本如:8.2.3,各级版本号都为数字且以’.’分割,当某一级别版本号大于等于10时,String.compareTo()方法返回错误。

一、String.compareTo()比较版本号

  通过String.compareTo()比较不同的版本号,结果如下:

public class Test {

    public static void main(String[] args) {

        System.out.println("\"8.2.3\".compareTo(\"8.2.3\") : " + "8.2.3".compareTo("8.2.3"));
        System.out.println("\"8.2.3\".compareTo(\"8.7.3\") : " + "8.2.3".compareTo("8.7.3"));
        System.out.println("\"8.2.3\".compareTo(\"8.1.1\") : " + "8.2.3".compareTo("8.1.1"));
        System.out.println("\"8.2.3\".compareTo(\"8.2.15\") : " + "8.2.3".compareTo("8.2.15"));
        System.out.println("\"8.2.3\".compareTo(\"8.2.a\") : " + "8.2.3".compareTo("8.2.a"));
        System.out.println("\"8.2.3\".compareTo(\"8.2.1.236\") : " + "8.2.3".compareTo("8.2.1.236"));
        System.out.println("\"8.2.3\".compareTo(\"8.8.1.236\") : " + "8.2.3".compareTo("8.8.1.236"));
        System.out.println("\"8.2.3\".compareTo(\"9.4\") : " + "8.2.3".compareTo("9.4"));
        System.out.println("\"8.2.3\".compareTo(\"6.4\") : " + "8.2.3".compareTo("6.4"));

    }

}

结果:
"8.2.3".compareTo("8.2.3") : 0
"8.2.3".compareTo("8.7.3") : -5
"8.2.3".compareTo("8.1.1") : 1
"8.2.3".compareTo("8.2.15") : 2
"8.2.3".compareTo("8.2.a") : -46
"8.2.3".compareTo("8.2.1.236") : 2
"8.2.3".compareTo("8.8.1.236") : -6
"8.2.3".compareTo("9.4") : -1
"8.2.3".compareTo("6.4") : 2

  以上大部分比较结果正确,但是版本号8.2.3与8.2.15的比较结果出现错误,8.2.3的版本应该比8.2.15的版本小。

  String.compareTo()源码如下,该方法比较逻辑为:按字符比较两个字符串,返回前k(两字符串中较短字符串的长度)个字符中第一个不同字符的差值,如果前k个字符都相同,则返回两个字符串的长度差值。  

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

...    
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
...
}
二、正确的版本号比较方法

  String.compareTo()方法适用于按字符比较的场景,不适用于版本号比较。我们使用到的客户端版本都是数字加分隔符(”.”)组合的,正确的方式应该按分隔符将版本号切分为各级版本,然后按级别比较版本号,如下:

public class Test {

    public static void main(String[] args) {

        Test test = new Test();

        System.out.println("compare(\"8.2.3\", \"8.2.3\") : " + test.compare("8.2.3", "8.2.3"));
        System.out.println("compare(\"8.2.3\", \"8.7.3\") : " + test.compare("8.2.3","8.7.3"));
        System.out.println("compare(\"8.2.3\", \"8.1.1\") : " + test.compare("8.2.3","8.1.1"));
        System.out.println("compare(\"8.2.3\", \"8.2.15\") : " + test.compare("8.2.3","8.2.15"));
        System.out.println("compare(\"8.2.3\", \"8.2.1.236\") : " + test.compare("8.2.3","8.2.1.236"));
        System.out.println("compare(\"8.2.3\", \"8.8.1.236\") : " + test.compare("8.2.3","8.8.1.236"));
        System.out.println("compare(\"8.2.3\", \"9.4\") : " + test.compare("8.2.3","9.4"));
        System.out.println("compare(\"8.2.3\", \"6.4\") : " + test.compare("8.2.3","6.4"));

    }

    public int compare(String v1, String v2) {
        if(StringUtils.isBlank(v1) && StringUtils.isBlank(v2)) {
            return 0;
        } else if(StringUtils.isBlank(v1)) {
            return -1;
        } else if(StringUtils.isBlank(v2)) {
            return 1;
        }

        int [] varr1 = getVersionArray(v1);

        int [] varr2 = getVersionArray(v2);

        int lim = Math.min(varr1.length, varr2.length);

        int k = 0;
        while(k < lim) {
            if(varr1[k] == varr2[k]) {
                k ++;
                continue;
            }
            return varr1[k] > varr2[k] ? 1 : -1;
        }

        if(varr1.length == varr2.length) {
            return 0;
        }

        return varr1.length > varr2.length ? 1 : -1;
    }

    public int [] getVersionArray(String v) {
        String [] sarray = StringUtils.split(v, ".");

        int [] varray = new int[sarray.length];

        int k = 0;

        while (k < sarray.length) {
            varray[k] = Integer.parseInt(sarray[k]);
            k ++;
        }

        return varray;
    }

}

结果:
compare("8.2.3", "8.2.3") : 0
compare("8.2.3", "8.7.3") : -1
compare("8.2.3", "8.1.1") : 1
compare("8.2.3", "8.2.15") : -1
compare("8.2.3", "8.2.1.236") : 1
compare("8.2.3", "8.8.1.236") : -1
compare("8.2.3", "9.4") : -1
compare("8.2.3", "6.4") : 1
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值