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

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10

当前回答

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

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'

其他回答

如果你的项目中已经有Jackson,你可以使用com.fasterxml.jackson.core.Version:

import com.fasterxml.jackson.core.Version;
import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class VersionTest {

    @Test
    public void shouldCompareVersion() {
        Version version1 = new Version(1, 11, 1, null, null, null);
        Version version2 = new Version(1, 12, 1, null, null, null);
        assertTrue(version1.compareTo(version2) < 0);
    }
}

由于本页上没有答案能很好地处理混合文本,我做了自己的版本:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Main {
    static double parseVersion(String v) {
        if (v.isEmpty()) {
            return 0;
        }
        Pattern p = Pattern.compile("^(\\D*)(\\d*)(\\D*)$");
        Matcher m = p.matcher(v);
        m.find();
        if (m.group(2).isEmpty()) {
            // v1.0.0.[preview]
            return -1;
        }
        double i = Integer.parseInt(m.group(2));
        if (!m.group(3).isEmpty()) {
            // v1.0.[0b]
            i -= 0.1;
        }
        return i;
    }

    public static int versionCompare(String str1, String str2) {
        String[] v1 = str1.split("\\.");
        String[] v2 = str2.split("\\.");
        int i = 0;
        for (; i < v1.length && i < v2.length; i++) {
            double iv1 = parseVersion(v1[i]);
            double iv2 = parseVersion(v2[i]);

            if (iv1 != iv2) {
                return iv1 - iv2 < 0 ? -1 : 1;
            }
        }
        if (i < v1.length) {
            // "1.0.1", "1.0"
            double iv1 = parseVersion(v1[i]);
            return iv1 < 0 ? -1 : (int) Math.ceil(iv1);
        }
        if (i < v2.length) {
            double iv2 = parseVersion(v2[i]);
            return -iv2 < 0 ? -1 : (int) Math.ceil(iv2);
        }
        return 0;
    }


    public static void main(String[] args) {
        System.out.println("versionCompare(v1.0.0, 1.0.0)");
        System.out.println(versionCompare("v1.0.0", "1.0.0")); // 0

        System.out.println("versionCompare(v1.0.0b, 1.0.0)");
        System.out.println(versionCompare("v1.0.0b", "1.0.0")); // -1

        System.out.println("versionCompare(v1.0.0.preview, 1.0.0)");
        System.out.println(versionCompare("v1.0.0.preview", "1.0.0")); // -1

        System.out.println("versionCompare(v1.0, 1.0.0)");
        System.out.println(versionCompare("v1.0", "1.0.0")); // 0

        System.out.println("versionCompare(ver1.0, 1.0.1)");
        System.out.println(versionCompare("ver1.0", "1.0.1")); // -1
    }
}

不过,在需要比较“alpha”和“beta”的情况下,它仍然不够。

对于要显示基于版本号的强制更新警报的人,我有以下想法。这可能用于比较Android当前应用版本和firebase远程配置版本之间的版本。这并不是问题的确切答案,但这肯定会对某人有所帮助。

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class Main
{
  static String firebaseVersion = "2.1.3"; // or 2.1
  static String appVersion = "2.1.4";
  static List<String> firebaseVersionArray;
  static List<String> appVersionArray;
  static boolean isNeedToShowAlert = false;
  public static void main (String[]args)
  {
    System.out.println ("Hello World");
    firebaseVersionArray = new ArrayList<String>(Arrays.asList(firebaseVersion.split ("\\.")));
    appVersionArray = new ArrayList<String>(Arrays.asList(appVersion.split ("\\.")));
    if(appVersionArray.size() < firebaseVersionArray.size()) {
        appVersionArray.add("0");
    }
    if(firebaseVersionArray.size() < appVersionArray.size()) {
        firebaseVersionArray.add("0");
    }
    isNeedToShowAlert = needToShowAlert(); //Returns false
    System.out.println (isNeedToShowAlert);

  }
  static boolean needToShowAlert() {
      boolean result = false;
      for(int i = 0 ; i < appVersionArray.size() ; i++) {
          if (Integer.parseInt(appVersionArray.get(i)) == Integer.parseInt(firebaseVersionArray.get(i))) {
              continue;
          } else if (Integer.parseInt(appVersionArray.get(i)) > Integer.parseInt(firebaseVersionArray.get(i))){
             result = false;
             break;
          } else if (Integer.parseInt(appVersionArray.get(i)) < Integer.parseInt(firebaseVersionArray.get(i))) {
             result = true;
             break;  
          }
      }
      return result;
  }
}

您可以通过复制粘贴来运行此代码 https://www.onlinegdb.com/online_java_compiler

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

 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;
    }

此代码尝试解决这种类型的比较版本。

大多数版本说明符,如>= 1.0,都是不言自明的。的 说明符~>具有特殊含义,最好通过示例来说明。~> 2.0.3是 与>= 2.0.3和< 2.1相同。~> 2.1与>= 2.1相同,且< 3.0.

public static boolean apply(String cmpDeviceVersion, String reqDeviceVersion)
{
    Boolean equal           = !cmpDeviceVersion.contains(">") && !cmpDeviceVersion.contains(">=") &&
                              !cmpDeviceVersion.contains("<") && !cmpDeviceVersion.contains("<=") &&
                              !cmpDeviceVersion.contains("~>");

    Boolean between         = cmpDeviceVersion.contains("~>");
    Boolean higher          = cmpDeviceVersion.contains(">") && !cmpDeviceVersion.contains(">=") && !cmpDeviceVersion.contains("~>");
    Boolean higherOrEqual   = cmpDeviceVersion.contains(">=");

    Boolean less            = cmpDeviceVersion.contains("<") && !cmpDeviceVersion.contains("<=");
    Boolean lessOrEqual     = cmpDeviceVersion.contains("<=");

    cmpDeviceVersion        = cmpDeviceVersion.replaceAll("[<>=~]", "");
    cmpDeviceVersion        = cmpDeviceVersion.trim();

    String[] version        = cmpDeviceVersion.split("\\.");
    String[] reqVersion     = reqDeviceVersion.split("\\.");

    if(equal)
    {
        return isEqual(version, reqVersion);
    }
    else if(between)
    {
        return isBetween(version, reqVersion);
    }
    else if(higher)
    {
        return isHigher(version, reqVersion);
    }
    else if(higherOrEqual)
    {
        return isEqual(version, reqVersion) || isHigher(version, reqVersion);
    }
    else if(less)
    {
        return isLess(version, reqVersion);
    }
    else if(lessOrEqual)
    {
        return isEqual(version, reqVersion) || isLess(version, reqVersion);
    }

    return false;
}

private static boolean isEqual(String[] version, String[] reqVersion)
{
    String strVersion = StringUtils.join(version);
    String strReqVersion = StringUtils.join(reqVersion);
    if(version.length > reqVersion.length)
    {
        Integer diff = version.length - reqVersion.length;
        strReqVersion += StringUtils.repeat(".0", diff);
    }
    else if(reqVersion.length > version.length)
    {
        Integer diff = reqVersion.length - version.length;
        strVersion += StringUtils.repeat(".0", diff);
    }

    return strVersion.equals(strReqVersion);
}

private static boolean isHigher(String[] version, String[] reqVersion)
{
    String strVersion = StringUtils.join(version);
    String strReqVersion = StringUtils.join(reqVersion);
    if(version.length > reqVersion.length)
    {
        Integer diff = version.length - reqVersion.length;
        strReqVersion += StringUtils.repeat(".0", diff);
    }
    else if(reqVersion.length > version.length)
    {
        Integer diff = reqVersion.length - version.length;
        strVersion += StringUtils.repeat(".0", diff);
    }

    return strReqVersion.compareTo(strVersion) > 0;
}

private static boolean isLess(String[] version, String[] reqVersion)
{
    String strVersion = StringUtils.join(version);
    String strReqVersion = StringUtils.join(reqVersion);
    if(version.length > reqVersion.length)
    {
        Integer diff = version.length - reqVersion.length;
        strReqVersion += StringUtils.repeat(".0", diff);
    }
    else if(reqVersion.length > version.length)
    {
        Integer diff = reqVersion.length - version.length;
        strVersion += StringUtils.repeat(".0", diff);
    }

    return strReqVersion.compareTo(strVersion) < 0;
}

private static boolean isBetween(String[] version, String[] reqVersion)
{
    return (isEqual(version, reqVersion) || isHigher(version, reqVersion)) &&
            isLess(getNextVersion(version), reqVersion);
}

private static String[] getNextVersion(String[] version)
{
    String[] nextVersion = new String[version.length];
    for(int i = version.length - 1; i >= 0 ; i--)
    {
        if(i == version.length - 1)
        {
            nextVersion[i] = "0";
        }
        else if((i == version.length - 2) && NumberUtils.isNumber(version[i]))
        {
            nextVersion[i] = String.valueOf(NumberUtils.toInt(version[i]) + 1);
        }
        else
        {
            nextVersion[i] = version[i];
        }
    }
    return nextVersion;
}