Version sammenligning i Java

1. Oversigt

Med udviklingen af ​​DevOps-teknologier er det almindeligt at opbygge og implementere en applikation flere gange om dagen.

Derfor, hver build tildeles et unikt versionsnummer, så vi kan skelne mellem builds. Nogle gange opstår der et behov for at sammenligne versionstrengene programmatisk.

I denne artikel undersøger vi et par måder at sammenligne versionstrenge i Java gennem forskellige biblioteker. Endelig skriver vi et brugerdefineret program til at håndtere generisk version-streng sammenligning.

2. Brug maven-artefakt

Lad os starte med at undersøge, hvordan Maven håndterer sammenligning af versioner.

2.1. Maven afhængighed

Først tilføjer vi det seneste maven-artefakt Maven afhængighed af vores pom.xml:

 org.apache.maven maven-artefakt 3.6.3 

2.2. Sammenlignelig version

Lad os udforske Sammenlignelig version klasse. Det giver en generisk implementering af versionssammenligning med et ubegrænset antal versionskomponenter.

Den indeholder en sammenligne med metode, og resultatet af sammenligningen vil være større end eller mindre end 0, når den ene version er større end henholdsvis mindre end den anden:

ComparableVersion version1_1 = ny ComparableVersion ("1.1"); ComparableVersion version1_2 = ny ComparableVersion ("1.2"); ComparableVersion version1_3 = ny ComparableVersion ("1.3"); assertTrue (version1_1.compareTo (version1_2) 0);

Her kan vi bekræfte, at 1.1-versionen er mindre end 1.2-versionen, og 1.3-versionen er større end 1.2-versionen.

Vi får dog 0 som et resultat, når vi sammenligner de samme versioner:

ComparableVersion version1_1_0 = ny ComparableVersion ("1.1.0"); assertEquals (0, version1_1.compareTo (version1_1_0));

2.3. Versionsadskillere og kvalifikatorer

Derudover er Sammenlignelig version klasse respekterer prikken (.) og bindestreg (-) som separatorer, hvor dot adskiller større og mindre versioner, og bindestrek definerer kvalifikatorer:

ComparableVersion version1_1_alpha = ny ComparableVersion ("1.1-alpha"); assertTrue (version1_1.compareTo (version1_1_alpha)> 0);

Her kan vi bekræfte, at 1.1-versionen er større end 1.1-alfa-versionen.

Der er et par velkendte kvalifikationer, der understøttes af Sammenlignelig version ligesom alfa, beta, milepæl, RCog øjebliksbillede (i rækkefølgen fra laveste til højeste):

ComparableVersion version1_1_beta = ny ComparableVersion ("1.1-beta"); ComparableVersion version1_1_milestone = ny ComparableVersion ("1.1-milepæl"); ComparableVersion version1_1_rc = ny ComparableVersion ("1.1-rc"); ComparableVersion version1_1_snapshot = ny ComparableVersion ("1.1-snapshot"); assertTrue (version1_1_alpha.compareTo (version1_1_beta) <0); assertTrue (version1_1_beta.compareTo (version1_1_milestone) <0); assertTrue (version1_1_rc.compareTo (version1_1_snapshot) <0); assertTrue (version1_1_snapshot.compareTo (version1_1) <0);

Også det giver os mulighed for at definere ukendte kvalifikatorer og respekterer deres rækkefølge efter de allerede diskuterede kendte kvalifikatorer med store og små bogstaver:

ComparableVersion version1_1_c = ny ComparableVersion ("1.1-c"); ComparableVersion version1_1_z = ny ComparableVersion ("1.1-z"); ComparableVersion version1_1_1 = ny ComparableVersion ("1.1.1"); assertTrue (version1_1_c.compareTo (version1_1_z) <0); assertTrue (version1_1_z.compareTo (version1_1_1) <0);

3. Brug gradle-core

Ligesom Maven har Gradle også den indbyggede evne til at håndtere versionssammenligning.

3.1. Maven afhængighed

Lad os først tilføje det seneste gradle-core Maven afhængighed fra Gradle Releases repo:

 org.gradle gradle-core 6.1.1 

3.2. VersionNummer

Det VersionNummer klasse leveret af Gradle sammenligner to versioner, der ligner Mavens Sammenlignelig version klasse:

VersionNumber version1_1 = VersionNumber.parse ("1.1"); VersionNumber version1_2 = VersionNumber.parse ("1.2"); VersionNumber version1_3 = VersionNumber.parse ("1.3"); assertTrue (version1_1.compareTo (version1_2) 0); VersionNumber version1_1_0 = VersionNumber.parse ("1.1.0"); assertEquals (0, version1_1.compareTo (version1_1_0)); 

3.3. Versionskomponenter

I modsætning til Sammenlignelig version klasse, den VersionNummer klasse understøtter kun fem versionskomponenter - Major, Mindre, Micro, Lappeog Kvalifikator:

VersionNumber version1_1_1_1_alpha = VersionNumber.parse ("1.1.1.1-alpha"); assertTrue (version1_1.compareTo (version1_1_1_1_alpha) <0); VersionNumber version1_1_beta = VersionNumber.parse ("1.1.0.0-beta"); assertTrue (version1_1_beta.compareTo (version1_1_1_1_alpha) <0);

3.4. Versionsskemaer

Også, VersionNummer understøtter et par forskellige versioner som f.eks Major.Minor.Micro-Qualifier og Major.Minor.Micro.Patch-kvalifikator:

VersionNumber version1_1_1_snapshot = VersionNumber.parse ("1.1.1-snapshot"); assertTrue (version1_1_1_1_alpha.compareTo (version1_1_1_snapshot) <0);

4. Brug jackson-core

4.1. Maven afhængighed

Svarende til andre afhængigheder, lad os tilføje det nyeste jackson-core Maven afhængighed af vores pom.xml:

 com.fasterxml.jackson.core jackson-core 2.11.1 

4.2. Version

Derefter kan vi undersøge Jacksons Version klasse, som kan indeholde versioneringsoplysninger for en komponent sammen med den valgfri groupId og artefaktId værdier.

Derfor konstruktøren af Version klasse tillader os at definere groupId og artefaktId, sammen med komponenter som Major, Mindreog Lappe:

public Version (int major, int minor, int patchLevel, String snapshotInfo, String groupId, String artifactId) {// ...}

Så lad os sammenligne et par versioner ved hjælp af Version klasse:

Version version1_1 = ny version (1, 1, 0, null, null, null); Version version1_2 = ny version (1, 2, 0, null, null, null); Version version1_3 = ny version (1, 3, 0, null, null, null); assertTrue (version1_1.compareTo (version1_2) 0); Version version1_1_1 = ny version (1, 1, 1, null, null, null); assertTrue (version1_1.compareTo (version1_1_1) <0);

4.3. Det snapshotInfo Komponent

Det snapshotInfo komponent bruges ikke, når man sammenligner to versioner:

Version version1_1_snapshot = ny version (1, 1, 0, "snapshot", null, null); assertEquals (0, version1_1.compareTo (version1_1_snapshot));

Derudover er Version klasse giver isSnapshot metode til at kontrollere, om versionen indeholder et øjebliksbillede komponent:

assertTrue (version1_1_snapshot.isSnapshot ());

4.4. Det groupId og artefaktId Komponenter

Også denne klasse sammenligner den leksikale rækkefølge af groupId og artefaktId versionskomponenter:

Version version1_1_maven = ny version (1, 1, 0, null, "org.apache.maven", null); Version version1_1_gradle = ny version (1, 1, 0, null, "org.gradle", null); assertTrue (version1_1_maven.compareTo (version1_1_gradle) <0);

5. Brug Semver4J

Det Semver4j bibliotek giver os mulighed for at følge reglerne for den semantiske versionsspecifikation i Java.

5.1. Maven afhængighed

Først tilføjer vi det seneste semver4j Maven afhængighed:

 com.vdurmont semver4j 3.1.0 

5.2. Semver

Derefter kan vi bruge Semver klasse for at definere en version:

Semver version1_1 = ny Semver ("1.1.0"); Semver version1_2 = ny Semver ("1.2.0"); Semver version1_3 = ny Semver ("1.3.0"); assertTrue (version1_1.compareTo (version1_2) 0); 

Internt analyserer den en version i komponenter som Major, Mindreog Lappe.

5.3. Version sammenligning

Også den Semver klasse kommer med forskellige indbyggede metoder som er større end, isLowerThanog er lig med til sammenligning af version:

Semver version1_1_alpha = ny Semver ("1.1.0-alpha"); assertTrue (version1_1.isGreaterThan (version1_1_alpha)); Semver version1_1_beta = ny Semver ("1.1.0-beta"); assertTrue (version1_1_alpha.isLowerThan (version1_1_beta)); assertTrue (version1_1.isEqualTo ("1.1.0"));

Ligeledes giver det diff metode, der returnerer hovedforskellen mellem de to versioner:

assertEquals (VersionDiff.MAJOR, version1_1.diff ("2.1.0")); assertEquals (VersionDiff.MINOR, version1_1.diff ("1.2.3")); assertEquals (VersionDiff.PATCH, version1_1.diff ("1.1.1"));

5.4. Version stabilitet

Også den Semver klasse kommer med er stabil metode til at kontrollere stabiliteten af ​​en version bestemt af tilstedeværelsen eller fraværet af et suffiks:

assertTrue (version1_1.isStable ()); assertFalse (version1_1_alpha.isStable ());

6. Brugerdefineret løsning

Vi har set et par løsninger til at sammenligne versionstrengene. Hvis de ikke fungerer i en bestemt brugssag, skal vi muligvis skrive en brugerdefineret løsning.

Her er et simpelt eksempel, der fungerer i nogle grundlæggende sager - det kan altid udvides, hvis vi har brug for noget mere.

Ideen her er at tokenisere versionstrengene ved hjælp af en punktafgrænser og derefter sammenligne heltalskonvertering af hver Snor token, begyndende fra venstre. Hvis tokens heltalværdi er den samme, skal du undersøge det næste token og fortsætte dette trin, indtil vi finder en forskel (eller indtil vi når det sidste token i en streng):

public static int compareVersions (String version1, String version2) {int comparisonResult = 0; Streng [] version1Splits = version1.split ("\."); Streng [] version2Splits = version2.split ("\."); int maxLengthOfVersionSplits = Math.max (version1Splits.length, version2Splits.length); for (int i = 0; i <maxLengthOfVersionSplits; i ++) {Heltal v1 = i <version1Splits.length? Integer.parseInt (version1Splits [i]): 0; Heltal v2 = i <version2Splits.length? Integer.parseInt (version2Splits [i]): 0; int sammenligne = v1.compareTo (v2); hvis (sammenlign! = 0) {sammenligningsresultat = sammenlign; pause; }} returner sammenligningResultat; }

Lad os kontrollere vores løsning ved at sammenligne et par versioner:

assertTrue (VersionCompare.compareVersions ("1.0.1", "1.1.2") <0); assertTrue (VersionCompare.compareVersions ("1.0.1", "1.10") 0); assertTrue (VersionCompare.compareVersions ("1.1.2", "1.2.0") <0); assertEquals (0, VersionCompare.compareVersions ("1.3.0", "1.3"));

Denne kode har en begrænsning, at den kun kan sammenligne et versionsnummer lavet af heltal afgrænset af prikker.

Derfor kan vi til at sammenligne alfanumeriske versionstrenge bruge et regulært udtryk til at adskille alfabeter og sammenligne den leksikale rækkefølge.

7. Konklusion

I denne artikel undersøgte vi forskellige måder at sammenligne versionstrenge i Java.

Først undersøgte vi indbyggede løsninger leveret af build-rammer som Maven og Gradle ved hjælp af maven-artefakt og gradle-core afhængigheder, henholdsvis. Derefter undersøgte vi funktioner til sammenligning af versioner af jackson-core og semver4j biblioteker.

Sidst skrev vi en brugerdefineret løsning til sammenligning af generiske versionstrenge.

Som normalt er alle kodeimplementeringer tilgængelige på GitHub.