APP的版本升级更新,会用到版本号的对比。根据版本号去解析埋点上报得信息。
正则匹配方式解析版本号中字符和数字做对比,默认字符大于数字(版本号1 是否大于等于 版本号2)。详见以下代码
@Slf4j
public class CompareUtil {
private static final Pattern num = Pattern.compile("[^0-9]");
private static final Pattern cha = Pattern.compile("\\D+");
/**
* 版本号对比, 默认字符大于数字: 如("10.0.1b", "10.0.1a")
* @param ver1 版本号1
* @param ver2 版本号2
* @return 版本号1 是否大于等于 版本号2
*/
public static boolean versionCompare(String ver1, String ver2) {
ver1 = StringUtils.isEmpty(ver1) ? "99.99": ver1;
ver2 = StringUtils.isEmpty(ver2) ? "99.99": ver2;
String[] verA = ver1.split("\\.", -1);
String[] verB = ver2.split("\\.", -1);
int com;
int len = Math.max(verA.length, verB.length);
// 补齐字符串数组
if (verA.length < len)
verA = stringExt(verA, len);
else if (verB.length < len)
verB = stringExt(verB, len);
for (int i = 0; i < len; i++) {
try {
com = Integer.parseInt(verA[i]) - Integer.parseInt(verB[i]);
} catch (Exception e) {
log.error(String.format("versionCompare err: ver1=>%s, ver1=>%s", ver1, ver2), e);
com = numAndCharCompare(verA[i], verB[i]);
}
if (com > 0) return true;
else if (com < 0) return false;
}
return true;
}
/**
* 数字与字符组成字符串大小比较,如:(10a 9a),(9a 9),(9b 9a)
* @param left
* @param right
* @return 1、0、-1
*/
public static int numAndCharCompare(String left, String right) {
left = left.length() == 0 ? "0" : left;
right = right.length() == 0 ? "0" : right;
// 判断字符串首字符是否为数字
boolean bL = left.charAt(0) >= 48 && left.charAt(0) <= 57;
boolean bR = right.charAt(0) >= 48 && right.charAt(0) <= 57;
if (bL && !bR)
return -1;
else if (!bL && bR)
return 1;
// 获取数字
String[] numLeft = num.matcher(left).replaceAll(",").split(",");
String[] numRight = num.matcher(right).replaceAll(",").split(",");
// 获取字符串
List<String> charLeft = new ArrayList<>();
List<String> charRight = new ArrayList<>();
Matcher matcherL = cha.matcher(left);
Matcher matcherR = cha.matcher(right);
while (matcherL.find()) {
charLeft.add(matcherL.group(0));
}
while (matcherR.find()) {
charRight.add(matcherR.group(0));
}
int numL = numLeft.length;
int numR = numRight.length;
int numLen = Math.max(numL, numR);
// 补齐字符串数组
if (numL < numLen)
numLeft = stringExt(numLeft, numLen);
else if (numR < numLen)
numRight = stringExt(numRight, numLen);
// 补齐List
int charL = charLeft.size();
int charR = charRight.size();
int charMax = Math.max(charL, charR);
if (charL < charMax)
listExt(charLeft, charL, charMax);
else if (charR < charMax)
listExt(charRight, charR, charMax);
int com = 0;
if (bL) // 同为数字开头
{
for (int i = 0; i < numLen; i++) {
com = Integer.parseInt(numLeft[i]) - Integer.parseInt(numRight[i]);
if (com == 0 && i < charMax)
com = charLeft.get(i).compareTo(charRight.get(i));
if (com > 0) return 1;
else if (com < 0) return -1;
}
}
else {
for (int i = 0; i < charMax; i++){
com = charLeft.get(i).compareTo(charRight.get(i));
if (com == 0 && i < numLen)
com = Integer.parseInt(numLeft[i+1]) - Integer.parseInt(numRight[i+1]);
if (com > 0) return 1;
else if (com < 0) return -1;
}
}
return 0;
}
/**
* 补齐字符串数组长度
* @param data 字符串数组
* @param len 补齐长度
* @return 补齐后的数组
*/
public static String[] stringExt(String[] data, int len) {
String[] res = new String[len];
int index = 0;
for (String datum : data) {
res[index++] = datum;
}
while (index < len){
res[index++] = "0";
}
return res;
}
/**
* 补齐List长度
* @param data list
* @param size 自身长度
* @param len 补齐长度
*/
public static void listExt(List<String> data, int size, int len) {
while (size < len) {
data.add("0");
size++;
}
}
public static void main(String[] args) {
System.out.println(versionCompare("10.0.0", "10.0.0"));
System.out.println(versionCompare("10.0.0", "9.0.0"));
System.out.println(versionCompare("10.1.0", "10.0.0"));
System.out.println(versionCompare("10.0.1b", "10.0.1a"));
System.out.println(versionCompare("10.0._0", "10.0._0_"));
System.out.println(versionCompare("9..", "9.0.0"));
}
}