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

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10

当前回答

我创建了一个简单的实用程序,使用语义版本约定在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。

其他回答

我自己写了一个小函数。更简单地使用列表

 public static boolean checkVersionUpdate(String olderVerison, String newVersion) {
        if (olderVerison.length() == 0 || newVersion.length() == 0) {
            return false;
        }
        List<String> newVerList = Arrays.asList(newVersion.split("\\."));
        List<String> oldVerList = Arrays.asList(olderVerison.split("\\."));

        int diff = newVerList.size() - oldVerList.size();
        List<String> newList = new ArrayList<>();
        if (diff > 0) {
            newList.addAll(oldVerList);
            for (int i = 0; i < diff; i++) {
                newList.add("0");
            }
            return examineArray(newList, newVerList, diff);
        } else if (diff < 0) {
            newList.addAll(newVerList);
            for (int i = 0; i < -diff; i++) {
                newList.add("0");
            }
            return examineArray(oldVerList, newList, diff);
        } else {
            return examineArray(oldVerList, newVerList, diff);
        }

    }

    public static boolean examineArray(List<String> oldList, List<String> newList, int diff) {
        boolean newVersionGreater = false;
        for (int i = 0; i < oldList.size(); i++) {
            if (Integer.parseInt(newList.get(i)) > Integer.parseInt(oldList.get(i))) {
                newVersionGreater = true;
                break;
            } else if (Integer.parseInt(newList.get(i)) < Integer.parseInt(oldList.get(i))) {
                newVersionGreater = false;
                break;
            } else {
                newVersionGreater = diff > 0;
            }
        }

        return newVersionGreater;
    }

下面是一个优化的实现:

public static final Comparator<CharSequence> VERSION_ORDER = new Comparator<CharSequence>() {

  @Override
  public int compare (CharSequence lhs, CharSequence rhs) {
    int ll = lhs.length(), rl = rhs.length(), lv = 0, rv = 0, li = 0, ri = 0;
    char c;
    do {
      lv = rv = 0;
      while (--ll >= 0) {
        c = lhs.charAt(li++);
        if (c < '0' || c > '9')
          break;
        lv = lv*10 + c - '0';
      }
      while (--rl >= 0) {
        c = rhs.charAt(ri++);
        if (c < '0' || c > '9')
          break;
        rv = rv*10 + c - '0';
      }
    } while (lv == rv && (ll >= 0 || rl >= 0));
    return lv - rv;
  }

};

结果:

"0.1" - "1.0" = -1
"1.0" - "1.0" = 0
"1.0" - "1.0.0" = 0
"10" - "1.0" = 9
"3.7.6" - "3.7.11" = -5
"foobar" - "1.0" = -1

使用Java 8 Stream替换组件中的前导零。这段代码通过了interviewbit.com上的所有测试

public int compareVersion(String A, String B) {
    List<String> strList1 = Arrays.stream(A.split("\\."))
                                           .map(s -> s.replaceAll("^0+(?!$)", ""))
                                           .collect(Collectors.toList());
    List<String> strList2 = Arrays.stream(B.split("\\."))
                                           .map(s -> s.replaceAll("^0+(?!$)", ""))
                                           .collect(Collectors.toList());
    int len1 = strList1.size();
    int len2 = strList2.size();
    int i = 0;
    while(i < len1 && i < len2){
        if (strList1.get(i).length() > strList2.get(i).length()) return 1;
        if (strList1.get(i).length() < strList2.get(i).length()) return -1;
        int result = new Long(strList1.get(i)).compareTo(new Long(strList2.get(i)));
        if (result != 0) return result;
        i++;
    }
    while (i < len1){
        if (!strList1.get(i++).equals("0")) return 1;
    }
    while (i < len2){
        if (!strList2.get(i++).equals("0")) return -1;
    }
    return 0;
}

使用Java 9自带的Version类

import java.util.*;
import java.lang.module.ModuleDescriptor.Version;
class Main {
  public static void main(String[] args) {
    var versions = Arrays.asList(
      "1.0.2",
      "1.0.0-beta.2",
      "1.0.0",
      "1.0.0-beta",
      "1.0.0-alpha.12",
      "1.0.0-beta.11",
      "1.0.1",
      "1.0.11",
      "1.0.0-rc.1",
      "1.0.0-alpha.1",
      "1.1.0",
      "1.0.0-alpha.beta",
      "1.11.0",
      "1.0.0-alpha.12.ab-c",
      "0.0.1",
      "1.2.1",
      "1.0.0-alpha",
      "1.0.0.1",  // Also works with a number of sections different than 3
      "1.0.0.2",
      "2",
      "10",
      "1.0.0.10"
    );
    versions.stream()
      .map(Version::parse)
      .sorted()
      .forEach(System.out::println);
  }
}

在网上试试!

输出:

0.0.1
1.0.0-alpha
1.0.0-alpha.1
1.0.0-alpha.12
1.0.0-alpha.12.ab-c
1.0.0-alpha.beta
1.0.0-beta
1.0.0-beta.2
1.0.0-beta.11
1.0.0-rc.1
1.0.0
1.0.0.1
1.0.0.2
1.0.0.10
1.0.1
1.0.2
1.0.11
1.1.0
1.2.1
1.11.0
2
10

最好的方法是重用现有代码, 使用Maven的ComparableVersion类

优点:

Apache许可证,版本2.0, 测试, 在多个项目中使用(复制),如spring-security-core, jboss等 多个特性 它已经是java.lang。可比的了 只是复制粘贴一个类,没有第三方依赖

不要包含对maven-artifact的依赖项,因为那会拉动各种传递依赖项