Java에서 두 버전 문자열을 어떻게 비교합니까?


155

버전 번호를 비교하기위한 표준 관용구가 있습니까? 나는 최대 포인트 릴리스 수를 아직 알지 못하기 때문에 직선 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 자리 이상의 숫자 가 있는지 확인하십시오 .
등록 된 사용자

4
@RegisteredUser이 작업은 다음과 같은 방식으로 어떻게 작동합니까 : 1.12.1 및 1.1.34?
kojow7

각 부품의 길이가 동일한 지 확인해야합니다. 따라서 예제의 두 버전을 비교하려면 1.12.01 및 1.01.34와 같은 형식이어야합니다. 자바에서는 먼저 .문자를 분할하고 각 요소 길이를 비교 하여이를 달성 할 수 있습니다. 그런 다음 모든 요소를 ​​하나의 문자열에 넣은 다음 int로 구문 분석 한 다음 동일한 방식으로 변환 된 다른 버전과 비교하십시오
RegisteredUser

답변:


58

점을 구분 기호로 사용하여 문자열을 토큰 화 한 다음 왼쪽부터 시작하여 정수 변환을 나란히 비교하십시오.


1
이것이 내가 의지해야 할 것으로 의심되는 것입니다. 여기에는 두 버전 문자열 중 더 짧은 토큰을 반복하는 것도 포함됩니다. 확인해 주셔서 감사합니다.
Bill the Lizard

38
항상 숫자 만있는 것은 아닙니다. 일부 앱에는 빌드 번호가 포함되며 베타 등의 경우 1.0.1b와 같은 항목이 포함될 수 있습니다.
존 가드너

2
어떻게합니까?
Big McLargeHuge

문자열을 숫자 섹션과 숫자가 아닌 섹션으로 나누는 정규식을 작성하십시오. 숫자 부분과 숫자가 아닌 부분을 사전 식으로 비교하십시오. (점으로 나 split 수도 있음)
toolforger

179

이 오래된 게시물에 대한 또 다른 해결책 (도움이되는 사람들을위한) :

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와 달리 전체 문자열을 "일치"합니다. ( 안드로이드 문서 - 자바 문서 )


2
이것이 IMHO 최고의 솔루션입니다. 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 <parts.length; i ++) {final int part = Integer.parseInt (parts [i]); if (part> 0) { hashCode + = PRIME [i] ^ 부분;}} return hashCode;}
Barry Irvine

Pattern.compile()논리가 O(N log N)복잡하게 호출되는 경우 최소한 암시 적 호출을 캐시해야합니다 .
Lukas Eder

이 구현은 equals (Object that)를 재정의하므로 hashCode ()를 재정의해야합니다. 동일한 두 객체는 ​​동일한 hashCode를 반환해야합니다. 그렇지 않으면 해시 컬렉션과 함께 이러한 객체를 사용하면 문제가 발생할 수 있습니다.
콜린 필립스

'new Version ( "1.0"). equals (new Version ( "1")'이 true를 반환하므로 버전 문자열을 해시 할 수 없습니다.이 방법은 작동하지만 비효율적입니다 ... // 계약 : 두 버전 //는 "1.0"이 "1"이므로 버전 문자열의 hashCode를 반환 할 수 없습니다 @Override public int hashCode () {return 1;}
Colin Phillips


106

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

이 페이지 에서 Maven Artifact에 대한 올바른 종속성 문자열을 얻을 수 있습니다 .

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

5
이 작업을 수행하는 방법에 대한 테스트로 요점을 만들었습니다. gist.github.com/2627608
yclian

11
완벽, 바퀴를 재발 명하지 마십시오!
Lluis Martinez

8
단 하나의 걱정은 : 한 가지 이유 때문에 많은 파일과 함께이 의존성을 사용하는 것입니다-하나의 클래스를 가지려면-DefaultArtifactVersion
ses

7
@ses 스토리지는 저렴합니다 – 원래 코드를 작성, 테스트 및 유지하는 것보다 확실히 저렴합니다
Alex Dean

11
Comparable.compareTo"음의 정수, 0 또는 양의 정수"를 반환 하는 것으로 문서화되어 있으므로 -1 및 +1을 확인하지 않는 것이 좋습니다.
seanf

52

비교할 수 있도록 버전 문자열을 정규화해야합니다. 같은 것

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'

2
정규화에 대한주의 사항은 거기에 포함 된 최대 너비입니다.
dlamblin

@IHeartAndroid 좋은 지적, '4.1'== '4.1.0'을 기대하지 않는 한 이것이 의미있는 주문이라고 생각합니다.
Peter Lawrey

내 대답을 확인, 나는 그의 대답 일반화 한 여기
Abhinav 푸리

48

기존 코드를 재사용하는 가장 좋은 방법은 Maven의 ComparableVersion 클래스를 사용하십시오.

장점 :

  • Apache 라이센스, 버전 2.0,
  • 테스트,
  • spring-security-core, jboss 등과 같은 여러 프로젝트에서 사용 (복사)
  • 여러 기능
  • 이미 java.lang.Comparable입니다.
  • 해당 클래스 하나만 복사하여 붙여 넣기, 타사 종속성 없음

maven-artifact에 대한 의존성을 포함하지 마십시오.


이것은 광고처럼 읽히고 다른 답변에는 아무것도 추가하지 않습니다.
eddie_cat

6
버전을 비교하는 표준 방법과 maven 버전 비교가 거의 표준이므로 질문과 관련이 있습니다.
Dileep

5
이것이 가장 좋은 대답입니다. 나는 많은 다른 사람들 (허용 된 것을 포함하여)이 테스트없이 해키 문자열 분리를 시도하는 것을 믿을 수 없다. 이 클래스를 사용하는 코드 예제 :assertTrue(new ComparableVersion("1.1-BETA").compareTo(new ComparableVersion("1.1-RC")) < 0)
Fabian Kessler

단점 : 다양한 종속성을 가져옵니다. 즉, 공격에 노출되어 있고 버전 충돌 가능성이 있습니다.
toolforger

35
// 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

18

왜 모든 사람들이 버전이 정수로만 구성되어 있다고 생각하는지 궁금합니다. 제 경우에는 그렇지 않았습니다.

휠을 재발 명하는 이유 (버전이 Semver 표준을 따르는 것으로 가정)

먼저 Maven을 통해 https://github.com/vdurmont/semver4j 를 설치 하십시오

그런 다음이 라이브러리를 사용하십시오.

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

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

1
간단한 경우에 유용합니다.
Christophe Roussy

귀하의 아이디어를 바탕으로 stackoverflow.com/a/62532745/2642478
Xan

4

프로젝트에 이미 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);
    }
}

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

2
/**  
 *  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
---------------

2

String 버전에서 작동하는 유틸리티가있는 MgntUtils라는 오픈 소스 라이브러리를 작성했습니다. 올바르게 비교하고 버전 범위 등에서 작동합니다. 여기이 라이브러리 javadoc 메소드가 TextUtils.comapreVersions(...)있습니다. 많이 사용되고 잘 테스트되었습니다. 다음은 라이브러리와 라이브러리를 설명 하는 기사 입니다. Maven 아티팩트로github 에서 사용할 수 있습니다 (소스 및 JavaDoc 포함)


1

내 프로젝트의 경우 내 commons-version 라이브러리 https://github.com/raydac/commons-version을 사용 합니다. 버전을 구문 분석하기 위해 (파싱 된 버전은 다른 버전 객체와 비교할 수 있으므로 구문 분석 된 버전은 다른 버전 객체와 비교할 수 있음) 및 VersionValidator 어떤 식에 대한 버전을 확인할 수 있습니다!=ide-1.1.1,>idea-1.3.4-SNAPSHOT;<1.2.3


1

나는 간단하게 만든 버전을 비교하는 유틸리티안드로이드 플랫폼을 사용하여 시맨틱 버전 관리 규칙을. 따라서 X, Y 및 Z가 음이 아닌 정수인 XYZ 형식 (Major.Minor.Patch)의 문자열에만 작동합니다. 내 GitHub 에서 찾을 수 있습니다 .

Version.compareVersions (String v1, String v2) 메서드 는 두 버전 문자열을 비교합니다. v 전이 v 전 v 전 v 전 v 전 v 전 v2 v 전 v2 v 전 v2 v 전 v2 v 전 v2 v 전 v2 v 전 v2 v 전 v2 v2 v2 v2 v2 v2 v2 v2 v2 v2 v2 v2 v2


GitHub 링크를 찾을 수 없습니다
aldok

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

0

약간의 기능을 직접 작성했습니다.

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

0

버전 번호를 비교하기 위해 작은 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;
  }

이 스 니펫은 오류 확인 또는 처리 기능을 제공하지 않습니다. 내 라이브러리 외에도 "1.2-rc"> "1.2-beta"와 같은 접미사도 지원합니다.


0

Java 8 Stream을 사용하여 구성 요소의 선행 0을 대체합니다. 이 코드는 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;
}

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

그래도 "알파"와 "베타"를 비교해야하는 경우에는 여전히 부족합니다.


0

버전 번호를 기반으로 강제 업데이트 알림을 표시하려는 사람에게는 다음 아이디어가 있습니다. 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 에서 복사하여 붙여 넣기하여이 코드를 실행할 수 있습니다.


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

0

나는 지금 그것을하고 자신에게 물었다, 맞습니까? 내 것보다 전에 가장 깨끗한 해결책을 찾지 못했기 때문에 :

다음 예제와 같이 문자열 버전 ( "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) {

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

    return false;
}

어떤 피드백을 기다리는 중 :)


0

Kotlin에 대한 @alex 의 게시물

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

0

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"))

-1

이 코드는이 유형의 비교 버전을 해결하려고합니다.

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

-1

@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 함수에서 두 줄의 주석 처리를 제거해야합니다).

쉽게 테스트!


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

-2

최적화 된 구현은 다음과 같습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.