How to Compare Two Version Strings in Java

How do you compare two version Strings in Java?

Tokenize the strings with the dot as delimiter and then compare the integer translation side by side, beginning from the left.

Efficient way to compare version strings in Java

Requires commons-lang3-3.8.1.jar for string operations.

/**
* Compares two version strings.
*
* Use this instead of String.compareTo() for a non-lexicographical
* comparison that works for version strings. e.g. "1.10".compareTo("1.6").
*
* @param v1 a string of alpha numerals separated by decimal points.
* @param v2 a string of alpha numerals separated by decimal points.
* @return The result is 1 if v1 is greater than v2.
* The result is 2 if v2 is greater than v1.
* The result is -1 if the version format is unrecognized.
* The result is zero if the strings are equal.
*/

public int VersionCompare(String v1,String v2)
{
int v1Len=StringUtils.countMatches(v1,".");
int v2Len=StringUtils.countMatches(v2,".");

if(v1Len!=v2Len)
{
int count=Math.abs(v1Len-v2Len);
if(v1Len>v2Len)
for(int i=1;i<=count;i++)
v2+=".0";
else
for(int i=1;i<=count;i++)
v1+=".0";
}

if(v1.equals(v2))
return 0;

String[] v1Str=StringUtils.split(v1, ".");
String[] v2Str=StringUtils.split(v2, ".");
for(int i=0;i<v1Str.length;i++)
{
String str1="",str2="";
for (char c : v1Str[i].toCharArray()) {
if(Character.isLetter(c))
{
int u=c-'a'+1;
if(u<10)
str1+=String.valueOf("0"+u);
else
str1+=String.valueOf(u);
}
else
str1+=String.valueOf(c);
}
for (char c : v2Str[i].toCharArray()) {
if(Character.isLetter(c))
{
int u=c-'a'+1;
if(u<10)
str2+=String.valueOf("0"+u);
else
str2+=String.valueOf(u);
}
else
str2+=String.valueOf(c);
}
v1Str[i]="1"+str1;
v2Str[i]="1"+str2;

int num1=Integer.parseInt(v1Str[i]);
int num2=Integer.parseInt(v2Str[i]);

if(num1!=num2)
{
if(num1>num2)
return 1;
else
return 2;
}
}
return -1;
}

Comparing two version strings (4.x.x.x, 5.x.x.x)

You could use the following code:

public static void main(String[] args) {
String version1 = "1.0.4.1";
String version2 = "1.0.6.1";

int result = compare(version1, version2);

if(result==1){
System.out.println("Latest version:"+version1);
}else if(result==-1){
System.out.println("Latest version:"+version2);
}else{
System.out.println("Both version same:"+version2);
}
}

public static int compare(String version1, String version2){

String ver1[]=version1.split("\\.");
String ver2[]=version2.split("\\.");
int counter =0;
int len1= ver1.length;
int len2= ver2.length;

for(String v:ver1){

if(len1>0 && len2>0 && v.compareTo(ver2[counter])>0 ){
return 1;
}else{
if(len1>0 && len2>0 && v.compareTo(ver2[counter])<0) {
return -1;
}else{
len1--;
len2--;
counter++;
}

}
}

if(ver1.length > ver2.length){
return 1;
}else
if(ver1.length < ver2.length){
return -1;
}

return 0;
}

Comparing of version in Java

Here is something to get you going - very simplistic:

public class Main {
public static void main(String[] args)
{

String version1 = "4.10";
String version2 = "4.5";

compareVersions(version1, version2);
}

private static void compareVersions(String v1, String v2) {
String[] versionSplit1 = v1.split("\\.");
String[] versionSplit2 = v2.split("\\.");
if (versionSplit1[0].equals(versionSplit2[0])) {
if (Integer.parseInt(versionSplit1[1]) > (Integer.parseInt(versionSplit2[1]))) {
System.out.println(v1 + " is bigger than " + v2);
} else if (Integer.parseInt(versionSplit1[1]) == (Integer.parseInt(versionSplit2[1]))){
System.out.println(v1 + " is equal to " + v2);
} else {
System.out.println(v2 + " is bigger than " + v1);
}
} else if (Integer.parseInt(versionSplit1[0]) > Integer.parseInt(versionSplit2[0])) {
System.out.println(v1 + " is bigger than " + v2);
} else {
System.out.println(v2 + " is bigger than " + v1);
}
}
}

Here's a very quick rough solution if I understand your problem correctly - I imagine you will need to extend this to suit your needs, but the idea stays.

  1. Convert your version into a String if it still isn't.
  2. Split by dot, you end up with two parts - e.g. the first part (4) and second part (10).
  3. Compare the first part (since it is a String, you will need to parse it to an Integer). If the first part is the same, compare the second part (you will need to parse it as well).

If you are using BigDecimal and you want to convert to String and keep the trailing zero's, try this:

double value = 4.10;
//convert double to BigDecimal
BigDecimal bigDecimalValue = BigDecimal.valueOf(value);
BigDecimal tempValue = bigDecimalValue.setScale(2, RoundingMode.CEILING);
//convert to String
System.out.println(tempValue.toPlainString()); //5.40

Then proceed as described with Strings above.

How do I compare strings in Java?

== tests for reference equality (whether they are the same object).

.equals() tests for value equality (whether they are logically "equal").

Objects.equals() checks for null before calling .equals() so you don't have to (available as of JDK7, also available in Guava).

Consequently, if you want to test whether two strings have the same value you will probably want to use Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true

// ... but they are not the same object
new String("test") == "test" // --> false

// ... neither are these
new String("test") == new String("test") // --> false

// ... but these are because literals are interned by
// the compiler and thus refer to the same object
"test" == "test" // --> true

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

You almost always want to use Objects.equals(). In the rare situation where you know you're dealing with interned strings, you can use ==.

From JLS 3.10.5. String Literals:

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.

Similar examples can also be found in JLS 3.10.5-1.

Other Methods To Consider

String.equalsIgnoreCase() value equality that ignores case. Beware, however, that this method can have unexpected results in various locale-related cases, see this question.

String.contentEquals() compares the content of the String with the content of any CharSequence (available since Java 1.5). Saves you from having to turn your StringBuffer, etc into a String before doing the equality comparison, but leaves the null checking to you.

Comparing version number strings (major, minor, revision, beta)

Here's one suggestion:

static int[] getVersionNumbers(String ver) {
Matcher m = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)(beta(\\d*))?")
.matcher(ver);
if (!m.matches())
throw new IllegalArgumentException("Malformed FW version");

return new int[] { Integer.parseInt(m.group(1)), // major
Integer.parseInt(m.group(2)), // minor
Integer.parseInt(m.group(3)), // rev.
m.group(4) == null ? Integer.MAX_VALUE // no beta suffix
: m.group(5).isEmpty() ? 1 // "beta"
: Integer.parseInt(m.group(5)) // "beta3"
};
}

static boolean isFirmwareNewer(String testFW, String baseFW) {

int[] testVer = getVersionNumbers(testFW);
int[] baseVer = getVersionNumbers(baseFW);

for (int i = 0; i < testVer.length; i++)
if (testVer[i] != baseVer[i])
return testVer[i] > baseVer[i];

return true;
}

It uses a little trick and translates the beta-part as follows:

  • "" (no beta suffix) → Beta MAX_INT
  • "beta" → Beta 1 (since it preceeds "beta2")
  • "betaX" → Beta X

Note that it return true if both versions are identical.

How can I compare software version number using JavaScript? (only numbers)

The basic idea to make this comparison would be to use Array.split to get arrays of parts from the input strings and then compare pairs of parts from the two arrays; if the parts are not equal we know which version is smaller.

There are a few of important details to keep in mind:

  1. How should the parts in each pair be compared? The question wants to compare numerically, but what if we have version strings that are not made up of just digits (e.g. "1.0a")?
  2. What should happen if one version string has more parts than the other? Most likely "1.0" should be considered less than "1.0.1", but what about "1.0.0"?

Here's the code for an implementation that you can use directly (gist with documentation):

function versionCompare(v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');

function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
}

if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}

if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}

if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}

for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}

if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}

if (v1parts.length != v2parts.length) {
return -1;
}

return 0;
}

This version compares parts naturally, does not accept character suffixes and considers "1.7" to be smaller than "1.7.0". The comparison mode can be changed to lexicographical and shorter version strings can be automatically zero-padded using the optional third argument.

There is a JSFiddle that runs "unit tests" here; it is a slightly expanded version of ripper234's work (thank you).

Important note: This code uses Array.map and Array.every, which means that it will not run in IE versions earlier than 9. If you need to support those you will have to provide polyfills for the missing methods.

How to Compare a String to Two Other Strings All in the Same Line Using .equals()

You can't use equals to compare with two strings unless you call it twice, like this:

String input = kb.next().toLowerCase(); 
boolean hit = input.equals("y") || input.equals("yes");

You could alternatively use a regex:

boolean hit = input.matches("y(es)?");

Or if you don't mind matching the string "ye" as well as "y" and "yes", you could use startsWith:

boolean hit = "yes".startsWith(input);


Related Topics



Leave a reply



Submit