【问题标题】:How do you compare two version Strings in Java?你如何比较Java中的两个版本字符串?
【发布时间】:2010-09-16 22:33:26
【问题描述】:

有比较版本号的标准习语吗?我不能只使用直接的 String compareTo,因为我还不知道最大发布点数是多少。我需要比较版本并满足以下条件:

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10

【问题讨论】:

  • 您是否尝试仅删除点并将结果字符串解析为整数?我目前正在使用类似于以下内容的内容:String version = "1.1.2".replace(".", "");int number = Integer.parseInt(version); // = 112。您可以将该数字与另一个数字进行比较,从而找到更新的版本。此外,您可以检查version 字符串是否与\\d+\\.\\d+\\.\\d 等某些特定模式匹配,以使结果至少具有3 位数字。
  • @RegisteredUser 这将如何与以下内容一起使用:1.12.1 和 1.1.34 ?
  • 您必须确保每个部分的长度相同。因此,要比较示例的两个版本,它们必须是这样的:1.12.01 和 1.01.34。在 java 中,您可以通过首先拆分 . 字符并比较每个元素的长度来实现这一点。之后只需将所有元素放入一个字符串中,然后将其解析为 int,然后将其与已以相同方式转换的另一个版本进行比较
  • 只是想分享一下,这在 groovy stackoverflow.com/a/7737400/1195507 中实现的时间可能非常短@

标签: java comparison versioning


【解决方案1】:

这个旧帖子的另一个解决方案(对于那些可能有帮助的人):

public class Version implements Comparable<Version> {

    private String version;

    public final String get() {
        return this.version;
    }

    public Version(String version) {
        if(version == null)
            throw new IllegalArgumentException("Version can not be null");
        if(!version.matches("[0-9]+(\\.[0-9]+)*"))
            throw new IllegalArgumentException("Invalid version format");
        this.version = version;
    }

    @Override public int compareTo(Version that) {
        if(that == null)
            return 1;
        String[] thisParts = this.get().split("\\.");
        String[] thatParts = that.get().split("\\.");
        int length = Math.max(thisParts.length, thatParts.length);
        for(int i = 0; i < length; i++) {
            int thisPart = i < thisParts.length ?
                Integer.parseInt(thisParts[i]) : 0;
            int thatPart = i < thatParts.length ?
                Integer.parseInt(thatParts[i]) : 0;
            if(thisPart < thatPart)
                return -1;
            if(thisPart > thatPart)
                return 1;
        }
        return 0;
    }

    @Override public boolean equals(Object that) {
        if(this == that)
            return true;
        if(that == null)
            return false;
        if(this.getClass() != that.getClass())
            return false;
        return this.compareTo((Version) that) == 0;
    }

}

Version a = new Version("1.1");
Version b = new Version("1.1.1");
a.compareTo(b) // return -1 (a<b)
a.equals(b)    // return false

Version a = new Version("2.0");
Version b = new Version("1.9.9");
a.compareTo(b) // return 1 (a>b)
a.equals(b)    // return false

Version a = new Version("1.0");
Version b = new Version("1");
a.compareTo(b) // return 0 (a=b)
a.equals(b)    // return true

Version a = new Version("1");
Version b = null;
a.compareTo(b) // return 1 (a>b)
a.equals(b)    // return false

List<Version> versions = new ArrayList<Version>();
versions.add(new Version("2"));
versions.add(new Version("1.0.5"));
versions.add(new Version("1.01.0"));
versions.add(new Version("1.00.1"));
Collections.min(versions).get() // return min version
Collections.max(versions).get() // return max version

// WARNING
Version a = new Version("2.06");
Version b = new Version("2.060");
a.equals(b)    // return false

编辑:

@daiscog:感谢您的评论,这段代码是为 Android 平台开发的,并且按照 Google 的建议,“匹配”方法检查整个字符串,这与使用规范模式的 Java 不同。 (Android documentation - JAVA documentation)

【讨论】:

  • 这是最好的解决方案恕我直言。我通过将其更改为 if (!version.matches("[0-9]+(\\.[0-9]+){0,2}") 并添加一个变量将其限制为 3 个元素版本代码: private static final int[] PRIME = { 2, 3, 5 }; 我能够为上述创建缺少的 hashCode:@Override public final int hashCode() { final String[] parts = this.get().split ("\\."); int hashCode = 0; for (int i = 0; i 0) { hashCode += PRIME[i] ^ part; } } return hashCode; }
  • 您至少应该缓存对Pattern.compile() 的隐式调用,因为您的逻辑是以O(N log N) 复杂性调用的。
  • 这个实现覆盖了equals(Object that),因此应该覆盖hashCode()。两个相等的对象必须返回相同的 hashCode 否则如果将这些对象与散列集合一起使用会遇到麻烦。
  • 您不能对版本字符串进行哈希处理,因为 'new Version("1.0").equals(new Version("1")' 将返回 true。这将起作用,但效率低下.. . // 合约:任何两个相等的版本必须返回相同的 hashCode。 // 因为“1.0”等于“1”,所以我们不能返回版本字符串的 hashCode。@Override public int hashCode() { return 1 ; }
【解决方案2】:

使用 Maven 真的很容易:

import org.apache.maven.artifact.versioning.DefaultArtifactVersion;

DefaultArtifactVersion minVersion = new DefaultArtifactVersion("1.0.1");
DefaultArtifactVersion maxVersion = new DefaultArtifactVersion("1.10");

DefaultArtifactVersion version = new DefaultArtifactVersion("1.11");

if (version.compareTo(minVersion) < 0 || version.compareTo(maxVersion) > 0) {
    System.out.println("Sorry, your version is unsupported");
}

您可以从this page 获取 Maven Artifact 的正确依赖字符串:

<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>3.0.3</version>
</dependency>

【讨论】:

  • 我已经创建了一个关于如何做到这一点的测试要点:gist.github.com/2627608
  • 完美,不要重复造轮子!
  • 只有一个担心是:使用这种包含大量文件的依赖项只是一个原因 - 拥有一个类 - DefaultArtifactVersion
  • @ses 存储很便宜 - 肯定比编写、测试和维护原始代码便宜
  • 请注意,Comparable.compareTo 被记录为返回“负整数、零或正整数”,因此避免检查 -1 和 +1 是一个好习惯。
【解决方案3】:

用点作为分隔符对字符串进行标记,然后从左侧开始并排比较整数翻译。

【讨论】:

  • 这是我怀疑我必须求助的。这还涉及在两个版本字符串中较短的一个中循环标记。感谢您的确认。
  • 别忘了你可能并不总是只有数字。一些应用程序将包含内部版本号,并且可能包含 1.0.1b 等内容。
  • 你是怎么做到的?
  • 您编写了一个将字符串拆分为数字和非数字部分的正则表达式。在数字上比较数字部分和按字典顺序比较非数字部分。 (也许也分点。)
  • 它在“.1”和“1”的情况下不起作用。同样,可能还有其他用例
【解决方案4】:

您需要规范化版本字符串,以便可以比较它们。类似的东西

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'

【讨论】:

  • 对规范化的警告是您在其中拥有的隐含最大宽度。
  • @IHeartAndroid 好点子,除非你期望 '4.1' == '4.1.0' 我认为这是一个有意义的排序。
【解决方案5】:

重用现有代码的最佳方式, 取Maven's ComparableVersion class

优点:

  • Apache 许可证,2.0 版,
  • 经过测试,
  • 在 spring-security-core、jboss 等多个项目中使用(复制)
  • 多个features
  • 已经是 java.lang.Comparable
  • 只需复制粘贴该类,没有第三方依赖项

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

【讨论】:

  • 这读起来像广告,并没有在其他答案中添加任何内容。
  • 这与问题相关,因为它是关于比较版本和 Maven 版本比较的标准方法。
  • 这是最好的答案。我不敢相信有多少其他人(包括被接受的)在没有测试的情况下尝试了一些 hacky 字符串拆分。使用此类的代码示例:assertTrue(new ComparableVersion("1.1-BETA").compareTo(new ComparableVersion("1.1-RC")) &lt; 0)
  • 缺点:引入大量依赖项,这意味着大量攻击面和版本冲突的可能性。
  • @toolforger,答案的最后一行建议不要将工件用作依赖项。相反,您可以只复制文件。就像在优势列表中所说的(两次)。
【解决方案6】:
// VersionComparator.java
import java.util.Comparator;

public class VersionComparator implements Comparator {

    public boolean equals(Object o1, Object o2) {
        return compare(o1, o2) == 0;
    }

    public int compare(Object o1, Object o2) {
        String version1 = (String) o1;
        String version2 = (String) o2;

        VersionTokenizer tokenizer1 = new VersionTokenizer(version1);
        VersionTokenizer tokenizer2 = new VersionTokenizer(version2);

        int number1 = 0, number2 = 0;
        String suffix1 = "", suffix2 = "";

        while (tokenizer1.MoveNext()) {
            if (!tokenizer2.MoveNext()) {
                do {
                    number1 = tokenizer1.getNumber();
                    suffix1 = tokenizer1.getSuffix();
                    if (number1 != 0 || suffix1.length() != 0) {
                        // Version one is longer than number two, and non-zero
                        return 1;
                    }
                }
                while (tokenizer1.MoveNext());

                // Version one is longer than version two, but zero
                return 0;
            }

            number1 = tokenizer1.getNumber();
            suffix1 = tokenizer1.getSuffix();
            number2 = tokenizer2.getNumber();
            suffix2 = tokenizer2.getSuffix();

            if (number1 < number2) {
                // Number one is less than number two
                return -1;
            }
            if (number1 > number2) {
                // Number one is greater than number two
                return 1;
            }

            boolean empty1 = suffix1.length() == 0;
            boolean empty2 = suffix2.length() == 0;

            if (empty1 && empty2) continue; // No suffixes
            if (empty1) return 1; // First suffix is empty (1.2 > 1.2b)
            if (empty2) return -1; // Second suffix is empty (1.2a < 1.2)

            // Lexical comparison of suffixes
            int result = suffix1.compareTo(suffix2);
            if (result != 0) return result;

        }
        if (tokenizer2.MoveNext()) {
            do {
                number2 = tokenizer2.getNumber();
                suffix2 = tokenizer2.getSuffix();
                if (number2 != 0 || suffix2.length() != 0) {
                    // Version one is longer than version two, and non-zero
                    return -1;
                }
            }
            while (tokenizer2.MoveNext());

            // Version two is longer than version one, but zero
            return 0;
        }
        return 0;
    }
}

// VersionTokenizer.java
public class VersionTokenizer {
    private final String _versionString;
    private final int _length;

    private int _position;
    private int _number;
    private String _suffix;
    private boolean _hasValue;

    public int getNumber() {
        return _number;
    }

    public String getSuffix() {
        return _suffix;
    }

    public boolean hasValue() {
        return _hasValue;
    }

    public VersionTokenizer(String versionString) {
        if (versionString == null)
            throw new IllegalArgumentException("versionString is null");

        _versionString = versionString;
        _length = versionString.length();
    }

    public boolean MoveNext() {
        _number = 0;
        _suffix = "";
        _hasValue = false;

        // No more characters
        if (_position >= _length)
            return false;

        _hasValue = true;

        while (_position < _length) {
            char c = _versionString.charAt(_position);
            if (c < '0' || c > '9') break;
            _number = _number * 10 + (c - '0');
            _position++;
        }

        int suffixStart = _position;

        while (_position < _length) {
            char c = _versionString.charAt(_position);
            if (c == '.') break;
            _position++;
        }

        _suffix = _versionString.substring(suffixStart, _position);

        if (_position < _length) _position++;

        return true;
    }
}

示例:

public class Main
{
    private static VersionComparator cmp;

    public static void main (String[] args)
    {
        cmp = new VersionComparator();
        Test(new String[]{"1.1.2", "1.2", "1.2.0", "1.2.1", "1.12"});
        Test(new String[]{"1.3", "1.3a", "1.3b", "1.3-SNAPSHOT"});
    }

    private static void Test(String[] versions) {
        for (int i = 0; i < versions.length; i++) {
            for (int j = i; j < versions.length; j++) {
                Test(versions[i], versions[j]);
            }
        }
    }

    private static void Test(String v1, String v2) {
        int result = cmp.compare(v1, v2);
        String op = "==";
        if (result < 0) op = "<";
        if (result > 0) op = ">";
        System.out.printf("%s %s %s\n", v1, op, v2);
    }
}

输出:

1.1.2 == 1.1.2                --->  same length and value
1.1.2 < 1.2                   --->  first number (1) less than second number (2) => -1
1.1.2 < 1.2.0                 --->  first number (1) less than second number (2) => -1
1.1.2 < 1.2.1                 --->  first number (1) less than second number (2) => -1
1.1.2 < 1.12                  --->  first number (1) less than second number (12) => -1
1.2 == 1.2                    --->  same length and value
1.2 == 1.2.0                  --->  first shorter than second, but zero
1.2 < 1.2.1                   --->  first shorter than second, and non-zero
1.2 < 1.12                    --->  first number (2) less than second number (12) => -1
1.2.0 == 1.2.0                --->  same length and value
1.2.0 < 1.2.1                 --->  first number (0) less than second number (1) => -1
1.2.0 < 1.12                  --->  first number (2) less than second number (12) => -1
1.2.1 == 1.2.1                --->  same length and value
1.2.1 < 1.12                  --->  first number (2) less than second number (12) => -1
1.12 == 1.12                  --->  same length and value

1.3 == 1.3                    --->  same length and value
1.3 > 1.3a                    --->  first suffix ('') is empty, but not second ('a') => 1
1.3 > 1.3b                    --->  first suffix ('') is empty, but not second ('b') => 1
1.3 > 1.3-SNAPSHOT            --->  first suffix ('') is empty, but not second ('-SNAPSHOT') => 1
1.3a == 1.3a                  --->  same length and value
1.3a < 1.3b                   --->  first suffix ('a') compared to second suffix ('b') => -1
1.3a < 1.3-SNAPSHOT           --->  first suffix ('a') compared to second suffix ('-SNAPSHOT') => -1
1.3b == 1.3b                  --->  same length and value
1.3b < 1.3-SNAPSHOT           --->  first suffix ('b') compared to second suffix ('-SNAPSHOT') => -1
1.3-SNAPSHOT == 1.3-SNAPSHOT  --->  same length and value

【讨论】:

    【解决方案7】:

    想知道为什么每个人都认为版本仅由整数组成 - 在我的情况下不是。

    为什么要重新发明轮子(假设版本遵循 Semver 标准)

    首先通过 Maven 安装 https://github.com/vdurmont/semver4j

    然后使用这个库

    Semver sem = new Semver("1.2.3");
    sem.isGreaterThan("1.2.2"); // true
    

    【讨论】:

      【解决方案8】:

      使用 Java 9 的 own builtin Version class

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

      Try it online!

      输出:

      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
      

      【讨论】:

      • 截至 2020 年,这应该是选定的答案。感谢发帖。
      【解决方案9】:
      public static int compareVersions(String version1, String version2){
      
          String[] levels1 = version1.split("\\.");
          String[] levels2 = version2.split("\\.");
      
          int length = Math.max(levels1.length, levels2.length);
          for (int i = 0; i < length; i++){
              Integer v1 = i < levels1.length ? Integer.parseInt(levels1[i]) : 0;
              Integer v2 = i < levels2.length ? Integer.parseInt(levels2[i]) : 0;
              int compare = v1.compareTo(v2);
              if (compare != 0){
                  return compare;
              }
          }
      
          return 0;
      }
      

      【讨论】:

      【解决方案10】:

      如果你的项目中已经有 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);
          }
      }
      

      【讨论】:

        【解决方案11】:

        @alex 在 Kotlin 上的 post

        class Version(inputVersion: String) : Comparable<Version> {
        
                var version: String
                    private set
        
                override fun compareTo(other: Version) =
                    (split() to other.split()).let {(thisParts, thatParts)->
                        val length = max(thisParts.size, thatParts.size)
                        for (i in 0 until length) {
                            val thisPart = if (i < thisParts.size) thisParts[i].toInt() else 0
                            val thatPart = if (i < thatParts.size) thatParts[i].toInt() else 0
                            if (thisPart < thatPart) return -1
                            if (thisPart > thatPart) return 1
                        }
                         0
                    }
        
                init {
                    require(inputVersion.matches("[0-9]+(\\.[0-9]+)*".toRegex())) { "Invalid version format" }
                    version = inputVersion
                }
            }
        
            fun Version.split() = version.split(".").toTypedArray()
        

        用法:

        Version("1.2.4").compareTo(Version("0.0.5")) //return 1
        

        【讨论】:

          【解决方案12】:
          public int compare(String v1, String v2) {
                  v1 = v1.replaceAll("\\s", "");
                  v2 = v2.replaceAll("\\s", "");
                  String[] a1 = v1.split("\\.");
                  String[] a2 = v2.split("\\.");
                  List<String> l1 = Arrays.asList(a1);
                  List<String> l2 = Arrays.asList(a2);
          
          
                  int i=0;
                  while(true){
                      Double d1 = null;
                      Double d2 = null;
          
                      try{
                          d1 = Double.parseDouble(l1.get(i));
                      }catch(IndexOutOfBoundsException e){
                      }
          
                      try{
                          d2 = Double.parseDouble(l2.get(i));
                      }catch(IndexOutOfBoundsException e){
                      }
          
                      if (d1 != null && d2 != null) {
                          if (d1.doubleValue() > d2.doubleValue()) {
                              return 1;
                          } else if (d1.doubleValue() < d2.doubleValue()) {
                              return -1;
                          }
                      } else if (d2 == null && d1 != null) {
                          if (d1.doubleValue() > 0) {
                              return 1;
                          }
                      } else if (d1 == null && d2 != null) {
                          if (d2.doubleValue() > 0) {
                              return -1;
                          }
                      } else {
                          break;
                      }
                      i++;
                  }
                  return 0;
              }
          

          【讨论】:

            【解决方案13】:
            /**  
             *  written by: Stan Towianski - May 2018 
             * notes: I make assumption each of 3 version sections a.b.c is not longer then 4 digits: aaaa.bbbb.cccc-MODWORD1(-)modnum2
             * 5.10.13-release-1 becomes 0000500100013.501     6.0-snapshot becomes 0000600000000.100
             * MODWORD1 = -xyz/NotMatching, -SNAPSHOT, -ALPHA, -BETA, -RC, -RELEASE/nothing  return:  .0, .1, .2, .3, .4, .5
             * modnum2 = up to 2 digit/chars second version
             * */
            public class VersionCk {
            
                private static boolean isVersionHigher( String baseVersion, String testVersion )
                    {
                    System.out.println( "versionToComparable( baseVersion ) =" + versionToComparable( baseVersion ) );
                    System.out.println( "versionToComparable( testVersion ) =" + versionToComparable( testVersion ) + " is this higher ?" );
                    return versionToComparable( testVersion ).compareTo( versionToComparable( baseVersion ) ) > 0;
                    }
            
                //----  not worrying about += for something so small
                private static String versionToComparable( String version )
                    {
            //        System.out.println("version - " + version);
                    String versionNum = version;
                    int at = version.indexOf( '-' );
                    if ( at >= 0 )
                        versionNum = version.substring( 0, at );
            
                    String[] numAr = versionNum.split( "\\." );
                    String versionFormatted = "0";
                    for ( String tmp : numAr )
                        {
                        versionFormatted += String.format( "%4s", tmp ).replace(' ', '0');
                        }
                    while ( versionFormatted.length() < 12 )  // pad out to aaaa.bbbb.cccc
                        {
                        versionFormatted += "0000";
                        }
            //        System.out.println( "converted min version =" + versionFormatted + "=   : " + versionNum );
                    return versionFormatted + getVersionModifier( version, at );
                    }
            
                //----  use order low to high: -xyz, -SNAPSHOT, -ALPHA, -BETA, -RC, -RELEASE/nothing  returns: 0, 1, 2, 3, 4, 5
                private static String getVersionModifier( String version, int at )
                    {
            //        System.out.println("version - " + version );
                    String[] wordModsAr = { "-SNAPSHOT", "-ALPHA", "-BETA", "-RC", "-RELEASE" };        
            
                    if ( at < 0 )
                        return "." + wordModsAr.length + "00";   // make nothing = RELEASE level
            
                    int i = 1;
                    for ( String word : wordModsAr )
                        {
                        if ( ( at = version.toUpperCase().indexOf( word ) ) > 0 )
                            return "." + i + getSecondVersionModifier( version.substring( at + word.length() ) );
                        i++;
                        }
            
                    return ".000";
                    }
            
                //----  add 2 chars for any number after first modifier.  -rc2 or -rc-2   returns 02
                private static String getSecondVersionModifier( String version )
                    {
                    System.out.println( "second modifier =" + version + "=" );
                    Matcher m = Pattern.compile("(.*?)(\\d+).*").matcher( version );
            //        if ( m.matches() )
            //            System.out.println( "match ? =" + m.matches() + "=   m.group(1) =" + m.group(1) + "=   m.group(2) =" + m.group(2) + "=   m.group(3) =" + (m.groupCount() >= 3 ? m.group(3) : "x") );
            //        else
            //            System.out.println( "No match" );
                    return m.matches() ? String.format( "%2s", m.group(2) ).replace(' ', '0') : "00";
                    }
            
                public static void main(String[] args) 
                    {
                    checkVersion( "3.10.0", "3.4.0");
                    checkVersion( "5.4.2", "5.4.1");
                    checkVersion( "5.4.4", "5.4.5");
                    checkVersion( "5.4.9", "5.4.12");
                    checkVersion( "5.9.222", "5.10.12");
                    checkVersion( "5.10.12", "5.10.12");
                    checkVersion( "5.10.13", "5.10.14");
                    checkVersion( "6.7.0", "6.8");
                    checkVersion( "6.7", "2.7.0");
                    checkVersion( "6", "6.3.1");
                    checkVersion( "4", "4.0.0");
                    checkVersion( "6.3.0", "6");
                    checkVersion( "5.10.12-Alpha", "5.10.12-beTA");
                    checkVersion( "5.10.13-release", "5.10.14-beta");
                    checkVersion( "6.7.0", "6.8-snapshot");
                    checkVersion( "6.7.1", "6.7.0-release");
                    checkVersion( "6-snapshot", "6.0.0-beta");
                    checkVersion( "6.0-snapshot", "6.0.0-whatthe");
                    checkVersion( "5.10.12-Alpha-1", "5.10.12-alpha-2");
                    checkVersion( "5.10.13-release-1", "5.10.13-release2");
                    checkVersion( "10-rc42", "10.0.0-rc53");
                    }
            
                private static void checkVersion(String baseVersion, String testVersion) 
                    {
                    System.out.println( "baseVersion - " + baseVersion );
                    System.out.println( "testVersion - " + testVersion );
                    System.out.println( "isVersionHigher = " + isVersionHigher( baseVersion, testVersion ) );
                    System.out.println( "---------------");
                    }
            
                }
            

            一些输出:

            ---------------
            baseVersion - 6.7
            testVersion - 2.7.0
            versionToComparable( baseVersion ) =0000600070000.500
            versionToComparable( testVersion ) =0000200070000.500 is this higher ?
            isVersionHigher = false
            ---------------
            baseVersion - 6
            testVersion - 6.3.1
            versionToComparable( baseVersion ) =0000600000000.500
            versionToComparable( testVersion ) =0000600030001.500 is this higher ?
            isVersionHigher = true
            ---------------
            baseVersion - 4
            testVersion - 4.0.0
            versionToComparable( baseVersion ) =0000400000000.500
            versionToComparable( testVersion ) =0000400000000.500 is this higher ?
            isVersionHigher = false
            ---------------
            baseVersion - 6.3.0
            testVersion - 6
            versionToComparable( baseVersion ) =0000600030000.500
            versionToComparable( testVersion ) =0000600000000.500 is this higher ?
            isVersionHigher = false
            ---------------
            baseVersion - 5.10.12-Alpha
            testVersion - 5.10.12-beTA
            second modifier ==
            versionToComparable( baseVersion ) =0000500100012.200
            second modifier ==
            versionToComparable( testVersion ) =0000500100012.300 is this higher ?
            second modifier ==
            second modifier ==
            isVersionHigher = true
            ---------------
            baseVersion - 5.10.13-release
            testVersion - 5.10.14-beta
            second modifier ==
            versionToComparable( baseVersion ) =0000500100013.500
            second modifier ==
            versionToComparable( testVersion ) =0000500100014.300 is this higher ?
            second modifier ==
            second modifier ==
            isVersionHigher = true
            ---------------
            baseVersion - 6.7.0
            testVersion - 6.8-snapshot
            versionToComparable( baseVersion ) =0000600070000.500
            second modifier ==
            versionToComparable( testVersion ) =0000600080000.100 is this higher ?
            second modifier ==
            isVersionHigher = true
            ---------------
            baseVersion - 6.7.1
            testVersion - 6.7.0-release
            versionToComparable( baseVersion ) =0000600070001.500
            second modifier ==
            versionToComparable( testVersion ) =0000600070000.500 is this higher ?
            second modifier ==
            isVersionHigher = false
            ---------------
            baseVersion - 6-snapshot
            testVersion - 6.0.0-beta
            second modifier ==
            versionToComparable( baseVersion ) =0000600000000.100
            second modifier ==
            versionToComparable( testVersion ) =0000600000000.300 is this higher ?
            second modifier ==
            second modifier ==
            isVersionHigher = true
            ---------------
            baseVersion - 6.0-snapshot
            testVersion - 6.0.0-whatthe
            second modifier ==
            versionToComparable( baseVersion ) =0000600000000.100
            versionToComparable( testVersion ) =0000600000000.000 is this higher ?
            second modifier ==
            isVersionHigher = false
            ---------------
            baseVersion - 5.10.12-Alpha-1
            testVersion - 5.10.12-alpha-2
            second modifier =-1=
            versionToComparable( baseVersion ) =0000500100012.201
            second modifier =-2=
            versionToComparable( testVersion ) =0000500100012.202 is this higher ?
            second modifier =-2=
            second modifier =-1=
            isVersionHigher = true
            ---------------
            baseVersion - 5.10.13-release-1
            testVersion - 5.10.13-release2
            second modifier =-1=
            versionToComparable( baseVersion ) =0000500100013.501
            second modifier =2=
            versionToComparable( testVersion ) =0000500100013.502 is this higher ?
            second modifier =2=
            second modifier =-1=
            isVersionHigher = true
            ---------------
            baseVersion - 10-rc42
            testVersion - 10.0.0-rc53
            second modifier =42=
            versionToComparable( baseVersion ) =0001000000000.442
            second modifier =53=
            versionToComparable( testVersion ) =0001000000000.453 is this higher ?
            second modifier =53=
            second modifier =42=
            isVersionHigher = true
            ---------------
            

            【讨论】:

              【解决方案14】:

              我编写了一个名为 MgntUtils 的开源库,它有一个适用于字符串版本的实用程序。它正确地比较它们,使用版本范围等等。这是这个库javadoc 请参阅方法TextUtils.comapreVersions(...)。它已被大量使用并经过良好测试。这是article,它描述了该库以及获取它的位置。它以Maven artifactgithub 的形式提供(带有源代码和JavaDoc)

              【讨论】:

                【解决方案15】:

                我现在就这样做了,问自己,对吗?因为我之前从未找到比我最干净的解决方案:

                你只需要像这个例子那样拆分字符串版本(“1.0.0”):

                userVersion.split("\\.")
                

                那么你将有:{"1", "0", "0"}

                现在,使用我所做的方法:

                isUpdateAvailable(userVersion.split("\\."), latestVersionSplit.split("\\."));
                

                方法:

                /**
                 * Compare two versions
                 *
                 * @param userVersionSplit   - User string array with major, minor and patch version from user (exemple: {"5", "2", "70"})
                 * @param latestVersionSplit - Latest string array with major, minor and patch version from api (example: {"5", "2", "71"})
                 * @return true if user version is smaller than latest version
                 */
                public static boolean isUpdateAvailable(String[] userVersionSplit, String[] latestVersionSplit) {
                
                    try {
                        int majorUserVersion = Integer.parseInt(userVersionSplit[0]);
                        int minorUserVersion = Integer.parseInt(userVersionSplit[1]);
                        int patchUserVersion = Integer.parseInt(userVersionSplit[2]);
                
                        int majorLatestVersion = Integer.parseInt(latestVersionSplit[0]);
                        int minorLatestVersion = Integer.parseInt(latestVersionSplit[1]);
                        int patchLatestVersion = Integer.parseInt(latestVersionSplit[2]);
                
                        if (majorUserVersion <= majorLatestVersion) {
                            if (majorUserVersion < majorLatestVersion) {
                                return true;
                            } else {
                                if (minorUserVersion <= minorLatestVersion) {
                                    if (minorUserVersion < minorLatestVersion) {
                                        return true;
                                    } else {
                                        return patchUserVersion < patchLatestVersion;
                                    }
                                }
                            }
                        }
                    } catch (Exception ignored) {
                        // Will be throw only if the versions pattern is different from "x.x.x" format
                        // Will return false at the end
                    }
                
                    return false;
                }
                

                等待任何反馈:)

                【讨论】:

                • 干净简洁——我喜欢。
                • 警告任何正在使用 kotlin 但想要得到这个答案的人,不要使用它。 Java String.split 的 in 参数是正则表达式,但 kotlin in 参数是字符串。这意味着对于 kotlin string.split(".") 就足够了。
                【解决方案16】:

                对于我的项目,我使用我的 commons-version 库 https://github.com/raydac/commons-version 它包含两个辅助类 - 解析版本(解析的版本可以与另一个版本对象进行比较,因为它是可比较的)和版本验证器,它允许检查某些表达式的版本,如!=ide-1.1.1,&gt;idea-1.3.4-SNAPSHOT;&lt;1.2.3

                【讨论】:

                  【解决方案17】:

                  我使用Semantic Versioning 约定在Android 平台 上创建了简单的utility for comparing versions。因此它仅适用于 X.Y.Z (Major.Minor.Patch) 格式的字符串,其中 X、Y 和 Z 是非负整数。你可以在我的GitHub找到它。

                  方法 Version.compareVersions(String v1, String v2) 比较两个版本字符串。如果版本相等返回0,如果版本v1在版本v2之前返回1,如果版本v1在版本v2之后返回-1,如果版本格式无效返回-2。

                  【讨论】:

                  • 找不到你的 GitHub 链接
                  【解决方案18】:
                  public int CompareVersions(String version1, String version2)
                  {
                      String[] string1Vals = version1.split("\\.");
                      String[] string2Vals = version2.split("\\.");
                  
                      int length = Math.max(string1Vals.length, string2Vals.length);
                  
                      for (int i = 0; i < length; i++)
                      {
                          Integer v1 = (i < string1Vals.length)?Integer.parseInt(string1Vals[i]):0;
                          Integer v2 = (i < string2Vals.length)?Integer.parseInt(string2Vals[i]):0;
                  
                          //Making sure Version1 bigger than version2
                          if (v1 > v2)
                          {
                              return 1;
                          }
                          //Making sure Version1 smaller than version2
                          else if(v1 < v2)
                          {
                              return -1;
                          }
                      }
                  
                      //Both are equal
                      return 0;
                  }
                  

                  【讨论】:

                    【解决方案19】:

                    基于https://stackoverflow.com/a/27891752/2642478

                    class Version(private val value: String) : Comparable<Version> {
                        private val splitted by lazy { value.split("-").first().split(".").map { it.toIntOrNull() ?: 0 } }
                    
                        override fun compareTo(other: Version): Int {
                            for (i in 0 until maxOf(splitted.size, other.splitted.size)) {
                                val compare = splitted.getOrElse(i) { 0 }.compareTo(other.splitted.getOrElse(i) { 0 })
                                if (compare != 0)
                                    return compare
                            }
                            return 0
                        }
                    }
                    

                    你可以像这样使用:

                        System.err.println(Version("1.0").compareTo( Version("1.0")))
                        System.err.println(Version("1.0") < Version("1.1"))
                        System.err.println(Version("1.10") > Version("1.9"))
                        System.err.println(Version("1.10.1") > Version("1.10"))
                        System.err.println(Version("0.0.1") < Version("1"))
                    

                    【讨论】:

                      【解决方案20】:

                      也许有人会对我的解决方案感兴趣:

                      class Version private constructor(private val versionString: String) : Comparable<Version> {
                      
                          private val major: Int by lazy { versionString.split(".")[0].toInt() }
                      
                          private val minor: Int by lazy { versionString.split(".")[1].toInt() }
                      
                          private val patch: Int by lazy {
                              val splitArray = versionString.split(".")
                      
                              if (splitArray.size == 3)
                                  splitArray[2].toInt()
                              else
                                  0
                          }
                      
                          override fun compareTo(other: Version): Int {
                              return when {
                                  major > other.major -> 1
                                  major < other.major -> -1
                                  minor > other.minor -> 1
                                  minor < other.minor -> -1
                                  patch > other.patch -> 1
                                  patch < other.patch -> -1
                                  else -> 0
                              }
                          }
                      
                          override fun equals(other: Any?): Boolean {
                              if (other == null || other !is Version) return false
                              return compareTo(other) == 0
                          }
                      
                          override fun hashCode(): Int {
                              return major * minor * patch
                          }
                      
                          companion object {
                              private fun doesContainsVersion(string: String): Boolean {
                                  val versionArray = string.split(".")
                      
                                  return versionArray.size in 2..3
                                          && versionArray[0].toIntOrNull() != null
                                          && versionArray[1].toIntOrNull() != null
                                          && (versionArray.size == 2 || versionArray[2].toIntOrNull() != null)
                              }
                      
                              fun from(string: String): Version? {
                                  return if (doesContainsVersion(string)) {
                                      Version(string)
                                  } else {
                                      null
                                  }
                              }
                          }
                      }
                      

                      用法:

                      val version1 = Version.from("3.2")
                      val version2 = Version.from("3.2.1")
                      version1 <= version2
                      
                      

                      【讨论】:

                      • 在计算版本之前我也忽略了字母或任何其他非数字字符
                      【解决方案21】:

                      由于此页面上没有答案可以很好地处理混合文本,因此我制作了自己的版本:

                      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”进行比较的情况下,它仍然不足。

                      【讨论】:

                        【解决方案22】:

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

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

                        【讨论】:

                          【解决方案23】:

                          我写了一个小的 Java/Android 库来比较版本号:https://github.com/G00fY2/version-compare

                          它的基本作用是这样的:

                            public int compareVersions(String versionA, String versionB) {
                              String[] versionTokensA = versionA.split("\\.");
                              String[] versionTokensB = versionB.split("\\.");
                              List<Integer> versionNumbersA = new ArrayList<>();
                              List<Integer> versionNumbersB = new ArrayList<>();
                          
                              for (String versionToken : versionTokensA) {
                                versionNumbersA.add(Integer.parseInt(versionToken));
                              }
                              for (String versionToken : versionTokensB) {
                                versionNumbersB.add(Integer.parseInt(versionToken));
                              }
                          
                              final int versionASize = versionNumbersA.size();
                              final int versionBSize = versionNumbersB.size();
                              int maxSize = Math.max(versionASize, versionBSize);
                          
                              for (int i = 0; i < maxSize; i++) {
                                if ((i < versionASize ? versionNumbersA.get(i) : 0) > (i < versionBSize ? versionNumbersB.get(i) : 0)) {
                                  return 1;
                                } else if ((i < versionASize ? versionNumbersA.get(i) : 0) < (i < versionBSize ? versionNumbersB.get(i) : 0)) {
                                  return -1;
                                }
                              }
                              return 0;
                            }
                          

                          这个 sn-p 不提供任何错误检查或处理。除此之外,我的库还支持“1.2-rc”>“1.2-beta”等后缀。

                          【讨论】:

                            【解决方案24】:

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

                            【讨论】:

                              【解决方案25】:

                              对于要根据版本号显示强制更新警报的人,我有以下想法。在比较 Android Current App 版本和 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

                              【讨论】:

                                【解决方案26】:
                                public static void main(String[] args) {
                                
                                    String version1 = "1.0";
                                    String version2 = "1.0.0";
                                    String[] version1_splits = version1.split("\\.");
                                    String[] version2_splits = version2.split("\\.");
                                    int length = version1_splits.length >= version2_splits.length ? version1_splits.length : version2_splits.length;
                                    int i=0;
                                    for(;i<length;i++){
                                        int version1_int = getValue(version1_splits,i);
                                        int version2_int = getValue(version2_splits,i);
                                        if(version1_int > version2_int){
                                            System.out.println("version1 > version2");
                                            break;
                                        }
                                        else if(version1_int < version2_int){
                                            System.out.println("version2 > version1");
                                            break;
                                        }
                                        else{
                                            if(i == length-1)
                                            System.out.println("version1 = version2");
                                        }
                                    }
                                }
                                
                                private static int getValue(String[] version1_splits, int i) {
                                    int temp;
                                    try{
                                        temp = Integer.valueOf(version1_splits[i]);
                                    }
                                    catch(IndexOutOfBoundsException e){
                                        temp=0;
                                    }
                                
                                    return temp;
                                }
                                

                                【讨论】:

                                  【解决方案27】:

                                  此代码尝试解析此类比较版本。

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

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

                                  【讨论】:

                                    【解决方案28】:

                                    我喜欢@Peter Lawrey 的想法,并且我将其扩展到更多限制:

                                        /**
                                        * Normalize string array, 
                                        * Appends zeros if string from the array
                                        * has length smaller than the maxLen.
                                        **/
                                        private String normalize(String[] split, int maxLen){
                                            StringBuilder sb = new StringBuilder("");
                                            for(String s : split) {
                                                for(int i = 0; i<maxLen-s.length(); i++) sb.append('0');
                                                sb.append(s);
                                            }
                                            return sb.toString();
                                        }
                                    
                                        /**
                                        * Removes trailing zeros of the form '.00.0...00'
                                        * (and does not remove zeros from, say, '4.1.100')
                                        **/
                                        public String removeTrailingZeros(String s){
                                            int i = s.length()-1;
                                            int k = s.length()-1;
                                            while(i >= 0 && (s.charAt(i) == '.' || s.charAt(i) == '0')){
                                              if(s.charAt(i) == '.') k = i-1;
                                              i--;  
                                            } 
                                            return s.substring(0,k+1);
                                        }
                                    
                                        /**
                                        * Compares two versions(works for alphabets too),
                                        * Returns 1 if v1 > v2, returns 0 if v1 == v2,
                                        * and returns -1 if v1 < v2.
                                        **/
                                        public int compareVersion(String v1, String v2) {
                                    
                                            // Uncomment below two lines if for you, say, 4.1.0 is equal to 4.1
                                            // v1 = removeTrailingZeros(v1);
                                            // v2 = removeTrailingZeros(v2);
                                    
                                            String[] splitv1 = v1.split("\\.");
                                            String[] splitv2 = v2.split("\\.");
                                            int maxLen = 0;
                                            for(String str : splitv1) maxLen = Math.max(maxLen, str.length());
                                            for(String str : splitv2) maxLen = Math.max(maxLen, str.length());
                                            int cmp = normalize(splitv1, maxLen).compareTo(normalize(splitv2, maxLen));
                                            return cmp > 0 ? 1 : (cmp < 0 ? -1 : 0);
                                        }
                                    

                                    希望它可以帮助某人。它通过了 interviewbit 和 leetcode 中的所有测试用例(需要在 compareVersion 函数中取消注释两行)。

                                    容易测试!

                                    【讨论】:

                                      【解决方案29】:

                                      最简单的解决方案是使用字符串比较。删除不需要的点或字母,以防版本类似于 v1.0.1Beta 使用 Regex("[^0-9]") 并且您获得 1.0 和 1.0.1 等版本:

                                      String ver1 = "10";
                                      String ver2 = "101";
                                          
                                      int res = ver1.compareTo(ver2);
                                      System.out.println("res: "+res);
                                      

                                      如果 ver1 按字典顺序小于 ver2,则返回负数,如果相等则返回 0,如果 ver1 大于则返回正数.

                                      compareTo() 方法按字典顺序比较两个字符串。

                                      比较基于字符串中每个字符的 Unicode 值。

                                      如果字符串等于另一个字符串,则该方法返回 0。如果字符串小于另一个字符串(更少字符),则返回小于 0 的值;如果字符串大于另一个字符串(更多字符),则返回大于 0 的值。

                                      【讨论】:

                                      • 这已经与给定样本之一中断,因为它比较 1.9 大于 1.10
                                      【解决方案30】:
                                      public class VersionComparator {
                                      
                                          /* loop through both version strings
                                           * then loop through the inner string to computer the val of the int
                                           * for each integer read, do num*10+<integer read>
                                           * and stop when stumbling upon '.'
                                           * When '.' is encountered...
                                           * see if '.' is encountered for both strings
                                           * if it is then compare num1 and num2 
                                           * if num1 == num2... iterate over p1++, p2++
                                           * else return (num1 > num2) ? 1 : -1
                                           * If both the string end then compare(num1, num2) return 0, 1, -1
                                           * else loop through the longer string and 
                                           * verify if it only has trailing zeros
                                           * If it only has trailing zeros then return 0
                                           * else it is greater than the other string
                                           */
                                          public static int compareVersions(String v1, String v2) {
                                              int num1 = 0;
                                              int num2 = 0;
                                              int p1 = 0;
                                              int p2 = 0;
                                      
                                              while (p1 < v1.length() && p2 < v2.length()) {
                                                  num1 = Integer.parseInt(v1.charAt(p1) + "");
                                                  num2 = Integer.parseInt(v2.charAt(p2) + "");
                                                  p1++;
                                                  p2++;
                                      
                                                  while (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) != '.' && v2.charAt(p2) != '.') {
                                                      if (p1 < v1.length()) num1 = num1 * 10 + Integer.parseInt(v1.charAt(p1) + "");
                                                      if (p2 < v2.length()) num2 = num2 * 10 + Integer.parseInt(v2.charAt(p2) + "");
                                                      p1++;
                                                      p2++;
                                                  }
                                      
                                                  if (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) == '.' && v2.charAt(p2) == '.') {
                                                      if ((num1 ^ num2) == 0) {
                                                          p1++;
                                                          p2++;
                                                      }
                                                      else return (num1 > num2) ? 1 : -1;
                                                  }
                                                  else if (p1 < v1.length() && p2 < v2.length() && v1.charAt(p1) == '.') return -1;
                                                  else if (p1 < v1.length() && p2 < v2.length() && v2.charAt(p2) == '.') return 1;
                                              }
                                      
                                              if (p1 == v1.length() && p2 == v2.length()) {
                                                  if ((num1 ^ num2) == 0) return 0;
                                                  else return (num1 > num2) ? 1 : -1;
                                              }
                                              else if (p1 == v1.length()) {
                                                  if ((num1 ^ num2) == 0) {
                                                      while (p2 < v2.length()) {
                                                          if (v2.charAt(p2) != '.' && v2.charAt(p2) != '0') return -1;
                                                          p2++;
                                                      }
                                                      return 0;
                                                  }
                                                  else return (num1 > num2) ? 1 : -1;
                                              }
                                              else {
                                                  if ((num1 ^ num2) == 0) {
                                                      while (p1 < v1.length()) {
                                                          if (v1.charAt(p1) != '.' && v1.charAt(p1) != '0') return 1;
                                                          p1++;
                                                      }
                                                      return 0;
                                                  }
                                                  else return (num1 > num2) ? 1 : -1;
                                              }
                                          }
                                      
                                          public static void main(String[] args) {
                                              System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
                                              System.out.println(compareVersions("11.21.1.0.0.1.0", "11.23") ^ -1);
                                              System.out.println(compareVersions("11.23", "11.23.0.0.0.1.0") ^ -1);
                                              System.out.println(compareVersions("11.2", "11.23") ^ -1);
                                              System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
                                              System.out.println(compareVersions("1.21.1.0.0.1.0", "2.23") ^ -1);
                                              System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
                                              System.out.println(compareVersions("11.23.0.0.0.0.0", "11.23") ^ 0);
                                              System.out.println(compareVersions("11.23", "11.21.1.0.0.1.0") ^ 1);
                                              System.out.println(compareVersions("1.5.1.3", "1.5.1.3.0") ^ 0);
                                              System.out.println(compareVersions("1.5.1.4", "1.5.1.3.0") ^ 1);
                                              System.out.println(compareVersions("1.2.1.3", "1.5.1.3.0") ^ -1);
                                              System.out.println(compareVersions("1.2.1.3", "1.22.1.3.0") ^ -1);
                                              System.out.println(compareVersions("1.222.1.3", "1.22.1.3.0") ^ 1);
                                          }
                                      }
                                      

                                      【讨论】:

                                        猜你喜欢
                                        • 1970-01-01
                                        • 2012-02-08
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 2013-05-04
                                        • 2018-06-14
                                        • 2014-11-15
                                        • 2012-08-02
                                        • 2012-04-29
                                        相关资源
                                        最近更新 更多