Skip to content

Instantly share code, notes, and snippets.

@yclian
Created May 7, 2012 12:54
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yclian/2627608 to your computer and use it in GitHub Desktop.
Save yclian/2627608 to your computer and use it in GitHub Desktop.
Version Comparator in Java
package foo;
import static java.util.regex.Pattern.compile;
import static org.apache.commons.lang3.StringUtils.substringAfter;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
/**
* <p>Utility to compare version.</p>
*
* @author yclian
* @since 20120507
* @version 20120507
*/
public final class Version {
private static final Pattern PATTERN_APPROXIMATION = compile("^([\\d\\.]+\\.)*(\\d+)$");
private ComparableVersion mVersion;
private Version(String v) {
mVersion = new ComparableVersion(v);
}
public static Version compare(String v) {
return new Version(v);
}
/**
* <p>Return the result of {@link Comparable#compareTo(Object)}. Very limited as it doesn't support {@code &gt;=}, {@code &lt;=} and {@code ~&gt;}.</p>
*
* @param v
* @return
*/
public int with(String v) {
return mVersion.compareTo(new ComparableVersion(v));
}
public boolean eq(String v) { return with(v) == 0; }
public boolean le(String v) { int c = with(v); return c == 0 || c == -1; }
public boolean lt(String v) { return with(v) == -1; }
public boolean ge(String v) { int c = with(v); return c == 0 || c == 1; }
public boolean gt(String v) { return with(v) == 1; }
/**
* <p>Approximately greater than, inspired by (and works exactly like) RubyGems.</p>
*
* @see <a href="http://docs.rubygems.org/read/chapter/16">RubyGems Manuals - Specifying Versions</a>
* @param v
* @return
*/
public boolean agt(String v) {
return ge(v) && lt(approximateUpper(v));
}
private String approximateUpper(String v) {
Matcher m = PATTERN_APPROXIMATION.matcher(v.split("\\.\\d+$")[0]);
if (m.find()) {
int i = Integer.parseInt(m.group(2));
return (null != m.group(1) ? m.group(1) : "") + ++i;
} else {
return v;
}
}
}
package foo;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static foo.Version.compare;
import org.junit.Before;
import org.junit.Test;
/**
* @author yclian
* @since 20120507
* @version 20120507
*/
public class VersionTest {
@Before
public void setUp() {}
@Test
public void testCompare() {
assertEquals(-1, compare("1.0.1").with("1.0.2"));
assertEquals(1, compare("1.0.2.1").with("1.0.2"));
assertTrue(compare("1.0.2").eq("1.0.2"));
}
@Test
public void testApproximation() {
assertTrue(compare("1.0.2").agt("1.0")); // ~> 1.0 => >= 1.0 && < 2.0
assertFalse(compare("2.0").agt("1.0"));
assertTrue(compare("1.9").agt("1.0")); // ~> 1.0 => >= 1.0 && < 2.0
assertFalse(compare("0.9").agt("1.0"));
assertTrue(compare("1.0.2").agt("1.0.2")); // ~> 1.0.2 => >= 1.0.2 && < 1.1
assertFalse(compare("1.2").agt("1.0.2"));
}
}
@yclian
Copy link
Author

yclian commented May 7, 2012

commons-lang3 is unnecessary.

@Sergey80
Copy link

Sergey80 commented May 6, 2013

what is the right maven dependency to use for org.apache.maven.artifact.versioning ?

@yclian
Copy link
Author

yclian commented Aug 5, 2013

@Sergey80: Try "maven-artifact".

@yclian
Copy link
Author

yclian commented Aug 5, 2013

@G00fY2
Copy link

G00fY2 commented Feb 5, 2018

For Android (or Java projects) you can use my tiny library which does not use external dependencies: https://github.com/G00fY2/version-compare

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment