就Android本身而言,其实大可不必比较字符版本号,Android系统本身升级应用的时候,也是由versionCode来判定版本大小的,而不是versionName。

defaultConfig {
        applicationId "com.xter.test"
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 1
        versionName "0.72"
        flavorDimensions "versionCode"
        buildConfigField("boolean", "LOG", "true")
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

然而出于某种考虑(也许是兼容其他平台比如服务端的版本号?),字符版本号还是用得相当多,那么更新的时候,就得把新老版本号拿出来比较了。

  • 方法一:转成long值比较
  • 方法二:比较字符串每位字符的char值即ASCII码大小
  • 方法三:直接使用compareTo方法
方法一

说出来自己都吓一跳,强迫症首先想到的是把字符串统一成数字来比较大小。

public static boolean compareVersion1(String version1, String version2) {
		String version1Number = version1.replace(".", "");
		String version2Number = version2.replace(".", "");
		if (version1Number.length() != version2Number.length()) {
			//长度不一,则按长度长者末尾补0
			if (version2Number.length() > version1Number.length()) {
				version1Number = version1Number + String.format(Locale.CHINA, "%" + 
	(version2Number.length() - version1Number.length()) + "d", 0);
			} else {
				version2Number = version2Number + String.format(Locale.CHINA, "%" + 
	(version1Number.length() - version2Number.length()) + "d", 0);
			}
		}
		return Long.parseLong(version2Number) > Long.parseLong(version1Number);
	}

想法很简洁,然而写出来就是这么一大坨…
又是去掉”."分隔符,又是补0,又是转long值…
并且,当你的版本号是这种“1.23.456.7890.1234567890“很长长度的时候,就不能比较了,为什么?因为long没有这么大…

Long.MAX_VALUE = 9223372036854775807

long的最大值都只有19位数,所以这种方法最好在版本号数字长度小于19的情况下使用。

或者把版本号拆成几段再转long值比较?


算了,不折腾了…

方法二

比较每一位的字符ASCII码大小,这样就避免了去除"."分隔符了,只要字符相同,ASCII码肯定是一样的,而数字较大,ASCII值也是较大的,那岂不是…
美滋滋?
当然还是要考虑两者长度不一样的情况。

public static boolean compareVersion2(String version1, String version2) {
		int lenMin = version1.length() < version2.length() ? version1.length() : version2.length();
		//两者差异值,此处是version2对versoin1
		int offset = 0;
		for (int i = 0; i < lenMin; i++) {
			offset = offset + version2.charAt(i) - version1.charAt(i);
			//若在高位已有差异,则跳出
			if (offset != 0) {
				break;
			}
		}
		if (offset == 0) {
			//若高位无差异,则长度大者更大
			offset = version2.length() - version1.length();
		}
		return offset > 0;
	}

果然美滋滋。
char和int值本就可以直接做运算(因为在JVM编译期间,boolean/byte/char/short都会扩展为相应的int类型数据)。
如果可以想到这个方法,其实已经够用了。

方法三

为什么会想到方法三?因为如果读过一点源码,肯定会觉得方法二的逻辑似曾相识…
先看下方法三的代码:

public static boolean compareVersion3(String version1, String version2) {
		if (version2.compareTo(version1) > 0) {
			return true;
		}
		return false;
	}

短小!
精悍!
为什么可以起作用?看compareTo的源码:

//String.java
    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;
    }

没有错,compareTo方法就是用的方法二,所以说如果想到了第二种方法,已经足够了,当然如果熟悉已有的API就更好了。

最后附上一段测试代码:

public static void main(String[] args) {
		String versoin1_1 = "1.4.5";
		String version1_2 = "1.4.6";
		System.out.println(compareVersion1(versoin1_1, version1_2));
		System.out.println(compareVersion2(versoin1_1, version1_2));
		System.out.println(compareVersion3(versoin1_1, version1_2));
		String version2_1 = "1.2.3";
		String version2_2 = "1.2";
		System.out.println(compareVersion1(version2_1, version2_2));
		System.out.println(compareVersion2(version2_1, version2_2));
		System.out.println(compareVersion3(version2_1, version2_2));
		String version3_1 = "1.8.4";
		String version3_2 = "1.9";
		System.out.println(compareVersion1(version3_1, version3_2));
		System.out.println(compareVersion2(version3_1, version3_2));
		System.out.println(compareVersion3(version3_1, version3_2));
		String version4_1 = "1.5.0";
		String version4_2 = "1.4.9.9";
		System.out.println(compareVersion1(version4_1, version4_2));
		System.out.println(compareVersion2(version4_1, version4_2));
		System.out.println(compareVersion3(version4_1, version4_2));
		String version5_1 = "0.72";
		String version5_2 = "0.719";
		System.out.println(compareVersion1(version5_1, version5_2));
		System.out.println(compareVersion2(version5_1, version5_2));
		System.out.println(compareVersion3(version5_1, version5_2));
		String version6_1 = "1.5.1111.543";
		String version6_2 = "1.5.1112.534";
		System.out.println(compareVersion1(version6_1, version6_2));
		System.out.println(compareVersion2(version6_1, version6_2));
		System.out.println(compareVersion3(version6_1, version6_2));
	}

以上。