Come si fa a confrontare due Stringhe in Java?

C’è uno standard idioma per confrontare i numeri di versione? Non posso utilizzare una scala di Stringa compareTo perché non so ancora quale sarà il numero massimo di punti di rilascio ci sarà. Ho bisogno di confrontare le versioni e di avere i seguenti è vero:

1.0 < 1.1
1.0.1 < 1.1
1.9 < 1.10
  • Hai provato a rimuovere i punti e analizzare la stringa risultante come un numero intero? Attualmente sto usando qualcosa di simile al seguente: String version = "1.1.2".replace(".", ""); int number = Integer.parseInt(version); // = 112. Si potrebbe confrontare il numero ad un altro e così trovare la versione più recente. Inoltre, è possibile verificare se il version stringa corrisponde a un determinato modello come \\d+\\.\\d+\\.\\d per rendere il risultato ha almeno 3 cifre.
  • Come sarebbe questo lavoro con qualcosa di simile a questo: 1.12.1 e 1.1.34 ?
  • Si dovrebbe fare in modo che ogni parte ha la stessa dimensione in lunghezza. Quindi, per confrontare le due versioni del tuo esempio, devono essere qualcosa di simile a questo: 1.12.01 e 1.01.34. In java si potrebbe ottenere questo dalla prima divisione alla . carattere e confronta elementi di lunghezza. Poi basta mettere tutti gli elementi in una stringa, quindi analizzare come int e poi confrontarlo con l’altra versione che è stata convertita allo stesso modo
  • Volevo solo condividere che questo potrebbe essere sorprendentemente breve implementato in groovy stackoverflow.com/a/7737400/1195507

 

21 Replies
  1. 55

    Simboleggiare le corde con il dot come delimitatore e, quindi, di confrontare l’intero traduzione a fianco, a partire da sinistra.

    • Questo è quello che ho sospettato, devo ricorrere alla. Questo comporta anche una loop sopra il token nel più breve tra due stringhe. Grazie per la conferma.
    • e non dimenticare che non sempre sono solo numeri. alcune applicazioni includono numeri di build, e potrebbe includere cose come 1.0.1 b per la beta/etc.
    • Come si fa a fare questo?
  2. 166

    Un’altra soluzione per questo vecchio post (per coloro che potrebbe essere d’aiuto) :

    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

    Edit:

    @daiscog: Grazie per il tuo commento, questo pezzo di codice è stato sviluppato per la piattaforma Android e come consigliato da Google, il metodo “corrisponde a” controllare l’intera stringa a differenza di Java che utilizza un modello regolamentare. (Android documentazioneLa documentazione JAVA)

    • brillant! +1 questo dovrebbe essere accettato risposta
    • Questa è la soluzione migliore IMHO. Mi sono limitato a 3 elemento versione codici modificando if (!versione.partite(“[0-9]+(\\.[0-9]+){0,2}”) e con l’aggiunta di una variabile: private static final int[] PRIMO = { 2, 3, 5 }; sono stato in grado di creare mancanti hashCode per il sopra: @Override public final int hashCode() { final String[] parti = questo.get().split(“\\.”); int hashCode = 0; for (int i = 0; i < parti.lunghezza; i++) { final int part = Integer.parseInt(parti[i]); if (parte > 0) { hashCode += PRIME[i] ^ parte; } } return hashCode; }
    • Sì, hai ragione.
    • L’analisi delle parti dovrebbe essere fatto solo una volta.
    • Si dovrebbe almeno cache implicito chiamate a Pattern.compile(), dato che la tua logica è chiamato con O(N log N) complessità.
    • questa implementazione esegue l’override di equals(Object) e, pertanto, dovrebbe sovrascrivere hashCode(). I due oggetti sono uguali deve restituire lo stesso hashCode altrimenti si può ottenere nei guai se si utilizzano questi oggetti con hash collezioni.
    • Non è possibile hash sulla stringa di versione dal “nuova Versione”1.0”).è uguale a(nuova Versione(“1”)’ restituisce vero. Questo funzionerà, ma è inefficiente … // contratto: due Versioni sono uguali deve restituire lo stesso hashCode. // dal “1.0” è uguale a “1”, non siamo in grado di restituire il codice hash della stringa di versione. @Override public int hashCode() { return 1; }

  3. 93

    È davvero facile con 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");
    }

    Si può ottenere il diritto di dipendenza stringa per Maven Artefatto da questa pagina:

    <dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-artifact</artifactId>
    <version>3.0.3</version>
    </dependency>
    • Ho creato un gist con test su come questo può essere fatto: gist.github.com/2627608
    • Grazie yclian – nizza!
    • Perfetto, non reinventare la ruota!
    • che cosa il diritto di dipendenza da includere per il mio pom.xml per che?
    • vedere aggiornato risposta
    • una sola preoccupazione è: per utilizzare questa dipendenza con un sacco di file in esso, solo per una ragione – di avere una classe – DefaultArtifactVersion
    • l’archiviazione è a buon mercato – sicuramente più economico rispetto a scrivere, testare e mantenere il codice originale
    • Nota che Comparable.compareTo è documentato come la restituzione di “un numero intero negativo, zero o un numero intero positivo”, quindi è una buona abitudine per evitare la verifica di -1 e +1.
    • Questo è del tutto sbagliato. Il compareTo in DefaultArtifactVersion spesso restituisce un valore diverso da 0, -1, 1, perché si sottrae un numero di versione di un altro. In tali casi, questo codice fallirà miseramente. E ‘ deludente vedere una risposta errata guadagnare tanti upvotes.
    • fatta modifica minore di utilizzare > e < a confrontare come indicato dalla documentazione (come sottolineato da @seanf). Inoltre, perché l’hai fatto DefaultArtifactVersion invece di ComparableVersion.
    • A quanto pare la mia modifica non passare attraverso (cercando di nuovo). Come @DavidWallace e seanf indicare il codice di cui sopra non è corretto. Alex, se si cattura di questo, si potrebbe fare la modifica.
    • Che non sembra funzionare con la versione Stringhe di lunghezza diversa: new DefaultArtifactVersion("1.2.1.1").compareTo(new DefaultArtifactVersion("1.1")) risultati in -1.

  4. 51

    È necessario normalizzare la versione stringhe possono essere confrontati. Qualcosa di simile

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

    Stampe

    '1.0' < '1.1'
    '1.0.1' < '1.1'
    '1.9' < '1.10'
    '1.a' > '1.9'
    • Avvertenza per la normalizzazione è implicita larghezza max in esso.
    • Grazie..tat funziona alla grande!!
    • Questo codice di risultati 4.1.0′ > ‘4.1’
    • Buon punto, a Meno che non si aspettano ‘4.1’ == ‘4.1.0’ penso che questo sia un senso di ordine.
    • check out la mia risposta, ho generalizzato la sua risposta qui
  5. 44

    Migliori per riutilizzare il codice esistente,
    prendere Maven è ComparableVersion classe

    vantaggi:

    • Licenza Apache, Versione 2.0,
    • testato,
    • utilizzato (copiato) in più progetti, come la primavera-sicurezza-core, jboss, ecc
    • più caratteristiche
    • è già un java.lang.Paragonabile
    • solo copia-incolla che una classe, senza dipendenze di terze parti

    Non includono la dipendenza di maven-manufatto che, come pull varie dipendenze transitive

    • Questo si legge come un annuncio e non aggiunge nulla alle altre risposte.
    • Questo per la questione, come è stato circa il metodo standard per confrontare le versioni e maven confronto di versione è praticamente standard.
    • Questa è la risposta migliore. Non riesco a credere come molti altri (tra cui accettato) provare alcune hacky stringa di scissione, senza prove. Il codice di esempio di utilizzo di questa classe: assertTrue(new ComparableVersion("1.1-BETA").compareTo(new ComparableVersion("1.1-RC")) < 0)
  6. 30
    //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;
        }
    }

    Esempio:

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

    Di uscita:

    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
    • il _hasValue variabile non è mai leggere
  7. 12

    Chiedendo perché ognuno si assume che le versioni è fatta solo di numeri interi, nel mio caso non è stato.

    Perché reinventare la ruota (supponendo che la versione segue la Semver standard)

    Che prima di installare https://github.com/vdurmont/semver4j via Maven

    Quindi utilizzare questa libreria

    Semver sem = new Semver("1.2.3");
    sem.isGreaterThan("1.2.2"); //true
  8. 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;
    }
    • Utile per i casi più semplici.
    • La soluzione intelligente per la maggior parte dei casi, grazie
  9. 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;
        }
  10. 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( "---------------");
            }
    
        }

    alcuni di uscita:

    ---------------
    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
    ---------------
  11. 2

    Se si dispone già di Jackson nel progetto, è possibile utilizzare 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);
        }
    }
  12. 1

    per i miei progetti, io uso il mio commons-versione biblioteca https://github.com/raydac/commons-version
    esso contiene due classi ausiliarie – analizzare versione (analizzato versione può essere confrontato con un altro versione in oggetto, in quanto esso è paragonabile) e VersionValidator che permette di controllare la versione per alcune espressioni come !=ide-1.1.1,>idea-1.3.4-SNAPSHOT;<1.2.3

  13. 1

    Ho creato semplice utilità per confrontare le versioni su piattaforma Android utilizzando Semantic Versioning convenzione. Quindi funziona solo per le stringhe in formato X. Y. Z (Maggiore.Minori.Patch) dove X, Y, e Z sono numeri interi non negativi. Lo si può trovare sul mio GitHub.

    Metodo Versione.compareVersions(String v1, String v2) confronta due stringhe. Restituisce 0 se le due versioni sono uguali, 1 se la versione v1 è la prima versione v2, -1 se la versione v1 è dopo la versione v2, -2 se la versione in formato non è valido.

    • il GitHub legame non è stato trovato
    • Ho aggiornato il link.
  14. 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;
    }
  15. 0

    Scritto un po ‘ la funzione di me stesso.Semplice Uso Di Elenchi

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

    Ho scritto una Libreria Open Source chiamato MgntUtils che è un programma di utilità che funziona con la Stringa versioni. Correttamente li confronta, funziona con la versione intervalli e così via. Ecco questa libreria javadoc Vedere metodi TextUtils.comapreVersions(...). È stato molto utilizzato e testato bene. Qui è il articolo che descrive la biblioteca e dove farlo. È disponibile come Maven artefatto e sul github (con fonti e javadoc)

  17. 0

    Ho scritto un piccolo Java/Android library per confrontare i numeri di versione: https://github.com/G00fY2/version-compare

    Cosa si fa fondamentalmente è questo:

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

    Questo frammento di codice non offre controlli di errore o di manipolazione. Accanto a questo il mio libreria supporta anche i suffissi come “1.2-rc” > “1.2-beta”.

  18. -1

    Questo codice provare a risolvere questo tipo di confronto versioni.

    Più della versione identificatori, come >= 1.0, sono auto-esplicative. Il
    identificatore di ~> ha un significato speciale, meglio dimostrato con l’esempio. ~> 2.0.3 è
    identico a >= 2.0.3 e < 2.1. ~> 2.1 è identico a >= 2.1 e <
    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;
    }
  19. -1

    Mi piaceva l’idea di @Pietro Lawrey, E l’ho esteso a ulteriori limiti :

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

    Speranza che aiuta qualcuno. Esso ha superato tutti i test in interviewbit e leetcode (necessario togliere il commento alle due linee di compareVersion funzione).

    Facilmente testato !

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

    Ecco un ottimizzata attuazione:

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

    Risultato:

    "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

Lascia un commento