System.out.println( Integer.valueOf(1).equals(Long.valueOf(1)) ); // false
Above print statement prints false, when using Integer and Long classes valueOf() methods respectively, the reason is very clear the two objects (Integer and the Long) have different types so they are not equal.
But, if passing integer value 1 and long value 1l to valueOf() method of string class, my print statement prints true
System.out.println( String.valueOf(1).equals(String.valueOf(1l)) ); // true
I am not able to understand what is exact difference between them.
I need explanation for that.
The answer is on the implementation of Integer#equals:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
You don't enter the if statement because they are of different types.
In the second version you are getting true because.. 1 is the same in String representation.
As you said, Integer and Long are different types, so equals returns false.
However, when comparing two Strings, if the value is the same (which is), equals returns true.
Conversion of Long or Integer to String is determined by the number it represents. Integer 1 and Long 1 have the same digits, so converting both to String give same results ("1").
Quite simply, the String representation of the number one is equal independent of what you use to retrieve that value. The valueOf method is overridden to work with ints and longs.
Your first experiment and your second experiment are not at all comparable.
Simple; regardless of whether the number 1 comes from an int, long, byte, or whatever, String.valueOf(1) -> "1". So you're running System.out.println("1".equals("1")), which is true.
Thats because in Java there are specific suffixes, for long (1L), float (1.4f) and double (-3.123d)..
Without any suffix, e.g. 1234 its being assumed to be an int. If its for example 3.1234 it would be assumed that its a double.
It doesnt matter if the suffix is in upper or lower case.
Integer.valueOf(1).equals(Long.valueOf(1)) // false
Yes, because Integer.ValueOf(1) result in an Integer instance and Integer.equals(Object) expects that the Object is a type Integer too.
String.valueOf(1).equals(String.valueOf(1l)) // true
Results is true, because both String.valueOf(1) and String.valueOf(1l) results in a string representing a number with plain character of digit. For example:
String.valueOf(12335454654465421L); will result in "12335454654465421"
Related
I read that the rule for the return value of these methods is that for obj1.compareTo(obj2) for example, if obj2 is under obj1 in the hierarchy, the return value is negative and if it's on top of obj1, then it's positive (and if it's equal then it's 0). However, in my class I saw examples where Math.signum was used in order to get -1 (for negative) and 1 (for positive) in the compareTo method.
Is there any reason for that?
EDIT:
Here is the code I meant:
Comparator comp = new Comparator() {
public int compare(Object obj1, Object obj2) {
Book book1 = (Book) obj1;
Book book2 = (Book) obj2;
int order = book1.getAuthor().compareTo(book2.getAuthor());
if (order == 0) {
order = (int) Math.signum(book1.getPrice() - book2.getPrice());
}
return order;
};
Is there any reason for using Math.signum
Yes there is.
order = (int) Math.signum(book1.getPrice() - book2.getPrice());
Suppose you have replace the above line with this
order = (int)(book1.getPrice() - book2.getPrice());
Now let us assume
book1.getPrice() returns 10.50
book2.getPrice() returns 10.40
If you do not use signum you will never have any compile time or run time error but value of order will be 0. This implies that book1 is equals to book2 which is logically false.
But if you use signum value of order will be 1 which implies book1 > book2.
But it must be mentioned that you should never make any assumption about compare function returning value between 1 and -1.
You can read official document for comparator http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html.
Any negative number will do to show that a < b. And any positive number will show that a > b. -1 and 1 serve that purpose just fine. There's no sense of being "more less than" or "more greater than"; they are binary attributes. The reason that any negative (or positive) value is permitted is probably historical; for integers it's common to implement the comparator by simple subtraction.
No.
PS: Frequent error in implementation is to use subtraction
public int compareTo(Object o) {
OurClass other = (OurClass)o; //Skip type check
return this.intField - other.intField;
}
It is wrong because if you call new OurClass(Integer.MIN_VALUE).compareTo(new OurClass(Integer.MAX_VALUE)) you get overflow. Probably Math.abs is attempt (failed) to deal with this problem.
The only reason I can see is that if you want to compare two ints for example (a and b), and you write
return a - b;
it might overflow. If you convert them to doubles and use (int)Math.signum( (double)a - (double)b ), you will definitely avoid that. But there are simpler ways of achieving the same effect, Integer.compare( a, b) for example.
If enum implements Comparable so why can't compare with < or >?
public class Dream
{
public static void main(String... args)
{
System.out.println(PinSize.BIG == PinSize.BIGGER); //false
System.out.println(PinSize.BIG == PinSize.BIG); //true
System.out.println(PinSize.BIG.equals(PinSize.BIGGER));//false
System.out.println(PinSize.BIG > PinSize.BIGGERER);// compilation error
//can't be compared
System.out.println(PinSize.BIG.toString().equals(PinSize.BIGGER));// #4
PinSize b = PinSize.BIG ;
System.out.println( b instanceof Comparable);// true
}
}
enum PinSize { BIG, BIGGER, BIGGERER };
You can do this:
PinSize.BIGGEST.ordinal() > PinSize.BIG.ordinal() // evaluates to `true`
Of course, assuming that BIGGEST was declared after BIG in the enumeration. The ordinal value in an enumeration is implicitly tied to the declaration order, by default the first value is assigned value 0, the second value 1 and so on.
So if yo declared the enumeration like this, things will work:
public enum PinSize {
SMALLEST, // ordinal value: 0
SMALL, // ordinal value: 1
NORMAL, // ordinal value: 2
BIG, // ordinal value: 3
BIGGER, // ordinal value: 4
BIGGEST; // ordinal value: 5
}
Implementing Comparable doesn't mean that you can use < or >. You can only use those with numeric values.
Implementing Comparable means that there's a compareTo() method. Try this:
System.out.println(PinSize.BIG.compareTo(PinSize.BIGGER));
The compareTo() method will return an int that is smaller than, equal to, or bigger than 0, depending on which value is "bigger". In the case of enum values, the "size" depends on the order of the enum value definitions.
The answers provided explain the problem well, but I would like to add my insights, because I feel that they don't answer question "why can't compare with < or >"?. The problem comes down to comparing references. PinSize.BIGGEST and PinSize.BIGGERER are reference variables. The same as the below:
String s;
int[] array;
MyObject myObject;
They represent addresses in memory. What is more, enums are singletons so there is always one object of the specified kind. Because of that the below line is allowed and returns true.
System.out.println(PinSize.BIG == PinSize.BIG); //true
Trying to check if one address in memory is greater or smaller than the other address in memory is impossible. Implementing Comparable interface and compareTo() method gives a chance to provide your own custom way of comparing objects not addresses in memory.
System.out.println(PinSize.BIG > PinSize.BIGGERER); // not possible
Let's first consider the following expressions in Java.
Integer temp = new Integer(1);
System.out.println(temp.equals(1));
if(temp.equals(1))
{
System.out.println("The if block executed.");
}
These all statements work just fine. There is no question about it. The expression temp.equals(1) is evaluated to true as expected and the only statement within the if block is executed consequently.
Now, when I change the data type from Integer to Long, the statement temp1.equals(1) is unexpectedly evaluated to false as follows.
Long temp1 = new Long(1);
System.out.println(temp1.equals(1));
if(temp1.equals(1))
{
System.out.println("The if block executed.");
}
These are the equivalent statements to those mentioned in the preceding snippet just the data type has been changed and they behave exactly opposite.
The expression temp1.equals(1) is evaluated to false and consequently, the only statement within the if block is not executed which the reverse of the preceding statements. How?
You're comparing a Long to an int. The javadoc for java.lang.Long#equals says that the equals method
Compares this object to the specified object. The result is true if and only if the argument is not null and is a Long object that contains the same long value as this object.
Instead try System.out.println(new Long(1).equals(1L)); Now that you're comparing a Long to a Long instead of a Long to an Integer, it will print true.
The reason you can do that comparison is because of autoboxing in Java.
The actual method you are calling is this:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Long.html#equals(java.lang.Object)
which is comparing your Long object to some other Object, not to an actual primitive int.
What happens when you call the method is that your primitive integer(1) is being autoboxed into an Object(Integer) so then you are effectively calling:
new Long(1).equals(new Integer(1));
which is why it fails.
This is why if you call
new Long(1).equals(1L)
this would work, because Java will autobox the 1L (primitive long, not int) into a Long object, not an Integer object.
The literal value 1 is not a long, it's an int. Try the above code with this instead:
System.out.println(temp1.equals(1L));
And
if (temp1.equals(1L))
As you can see, putting an L after the literal value 1 indicates that it's a long, and then the comparisons work as expected.
Java is being lazy.
When you perform the following comparison java will automatically cast the int to a long (as a long can contain any value an int can contain). And the comparison is between two longs and not two ints.
int i = 1;
long l = 1L;
boolean b = i == l;
Java is able to do this because the type information about i and l is known at compile time and when performing the comparison. However, when you use the boxed version the type can be known at compile time, but not when performing the comparison. This is because the comparison has to done within an equals method, and since equals takes Object as a parameter the type information is lost. Thus Java is lazy and only checks to see if two boxed numbers are equal if they are both of instances of same Number class (eg. both Integer, or both Long, or both Double, etc...).
Turns out the only fully reliable way to compare two numbers of unknown type at runtime is to convert both to strings and both to BigDecimal and then to use the method compareTo (and not equals). Though if you know you are only ever going to get longs and ints then life is simpler as you can just do the following.
Number n0 = new Long(1L);
Number n1 = new Integer(1);
boolean equal = n0.longValue() == n1.longValue();
According to Javadoc's page on Long, the .equals method evaluates to true only if
The argument is a Long object
If (1) is true, then the Long objects must have equal values
In your scenario, 1 is an int, not a Long object, so it fails (1), and therefore, evaluates to false. If you need to test to a long, use 1L instead.
That behaviour is consistent with autoboxing converting the 1 to an Integer which then compares equal to another Integer(1). Comparing a Long to an Integer yields false.
If you would use 1L to compare against Long it would yield true.
Long temp1 = new Long(1); System.out.println(temp1.equals(1));
if(temp1.equals(1)) {
System.out.println("The if block executed."); }
in this code temp1.equals(1) is comparing a Long object to Integer object which gives the result false ,we can correct it by using 1L instead of 1 ,,,eg temp1.equals(1L), by doing this we are comparing Long object with a Long and gives result TRUE
The implementation of equals() method of class Long illustrates why:
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
The equals method in Java.lang.Long initially starts with an instanceOf Long check only after that the value is compared.
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
So if you are going to use and Integer Value int the place of a Long value then the first check fails and hence you will get false as the result .
You can compare Long/integer values without uting equals(). This is only needed when you are comparing strings as far as I know.
I have a code snippet which I am not able to understand what exactly it does..
This code is in JavaBean..
private Object myNumb;
//then getter and setter for this
public int compareTo(myRptObj o){
if (myNumb instanceof String && o.myNumb instanceof Integer) {
return_value = 1;
} else if (myNumb instanceof Integer && o.myNumb instanceof String) {
return_value = -1;
} else if (myNumb instanceof String && o.myNumb instanceof String) {
return_value = ((String) myNumb).compareTo((String)o.myNumb);
} else if (myNumb instanceof Integer && o.myNumb instanceof Integer) {
return_value = ((Integer) myNumb).compareTo((Integer)o.myNumb);
}
}
I want to understand compareTo and how the comparison for String and Integer is done?
myNumb can be of type Integer or String.
The snippet makes sure that any Integer compares less than any String.
Integer-Integer and String-String comparisons are done the way you'd expect.
the first two if clauses ensure that Strings are considered greater than integers. The second two if clauses delegate the comparison between Strings and between Integers to the compareTo() implementation of these classes so that they are ordered as usual.
Note that it is very, very bad design to have this kind of code where a variable can be "of type X or Y" - exactly because it forces you to write code like this.
Instead, decide on one type and convert to/from that type where necessary.
... what exactly it does.
Basically: strings are greater than integers, if both are the same type use their natural ordering (either compare 2 strings or 2 integers).
Since myNumb can be either a String or an Integer, compareTo is checking what types they are first. If they are not the same type (one is an Integer and one is a String) they are not equal and therefore returns 1 or -1 as appropriate. If they are of the same type, it is casting them to that type and delegating to that type's compareTo.
When testing for equality of String's in Java I have always used equals() because to me this seems to be the most natural method for it. After all, its name already says what it is intended to do. However, a colleague of mine recently told me had been taught to use compareTo() == 0 instead of equals(). This feels unnatural (as compareTo() is meant to provide an ordering and not compare for equality) and even somewhat dangerous (because compareTo() == 0 does not necessarily imply equality in all cases, even though I know it does for String's) to me.
He did not know why he was taught to use compareTo() instead of equals() for String's, and I could also not find any reason why. Is this really a matter of personal taste, or is there any real reason for either method?
A difference is that "foo".equals((String)null) returns false while "foo".compareTo((String)null) == 0 throws a NullPointerException. So they are not always interchangeable even for Strings.
The 2 main differences are that:
equals will take any Object as a parameter, but compareTo will only take Strings.
equals only tells you whether they're equal or not, but compareTo gives information on how the Strings compare lexicographically.
I took a look at the String class code, and the algorithm within compareTo and equals looks basically the same. I believe his opinion was just a matter of taste, and I agree with you -- if all you need to know is the equality of the Strings and not which one comes first lexicographically, then I would use equals.
When comparing for equality you should use equals(), because it expresses your intent in a clear way.
compareTo() has the additional drawback that it only works on objects that implement the Comparable interface.
This applies in general, not only for Strings.
compareTo has do do more work if the strings have different lengths. equals can just return false, while compareTo must always examine enough characters to find the sorting order.
In String Context:
compareTo: Compares two strings lexicographically.
equals: Compares this string to the specified object.
compareTo compares two strings by their characters (at same index) and returns an integer (positive or negative) accordingly.
String s1 = "ab";
String s2 = "ab";
String s3 = "qb";
s1.compareTo(s2); // is 0
s1.compareTo(s3); // is -16
s3.compareTo(s1); // is 16
compareTo() not only applies to Strings but also any other object because compareTo<T> takes a generic argument T. String is one of the classes that has implemented the compareTo() method by implementing the Comparable interface.(compareTo() is a method fo the comparable Interface). So any class is free to implement the Comparable interface.
But compareTo() gives the ordering of objects, used typically in sorting objects in ascending or descending order while equals() will only talk about the equality and say whether they are equal or not.
equals() can be more efficient then compareTo().
A very important difference between compareTo and equals:
"myString".compareTo(null); //Throws java.lang.NullPointerException
"myString".equals(null); //Returns false
equals() checks if two objects are the same or not and returns a boolean.
compareTo() (from interface Comparable) returns an integer. It checks which of the two objects is "less than", "equal to" or "greater than" the other. Not all objects can be logically ordered, so a compareTo() method doesn't always make sense.
Note that equals() doesn't define the ordering between objects, which compareTo() does.
Now I advise you to review the source code of both methods to conclude that equals is preferable over compareTo that involves some Math calculations.
It appears that both methods pretty much do the same thing, but the compareTo() method takes in a String, not an Object, and adds some extra functionality on top of the normal equals() method. If all you care about is equality, then the equals() method is the best choice, simply because it makes more sense to the next programmer that takes a look at your code. The time difference between the two different functions shouldn't matter unless you're looping over some huge amount of items. The compareTo() is really useful when you need to know the order of Strings in a collection or when you need to know the difference in length between strings that start with the same sequence of characters.
source: http://java.sun.com/javase/6/docs/api/java/lang/String.html
equals() should be the method of choice in the case of the OP.
Looking at the implementation of equals() and compareTo() in java.lang.String on grepcode, we can easily see that equals is better if we are just concerned with the equality of two Strings:
equals():
1012 public boolean equals(Object anObject) {1013 if (this == anObject) {1014 return true;1015 }1016 if (anObject instanceof String) {1017 String anotherString = (String)anObject;1018 int n = count;1019 if (n == anotherString.count) {1020 char v1[] = value;1021 char v2[] = anotherString.value;1022 int i = offset;1023 int j = anotherString.offset;1024 while (n-- != 0) {1025 if (v1[i++] != v2[j++])1026 return false;1027 }1028 return true;1029 }1030 }1031 return false;1032 }
and compareTo():
1174 public int compareTo(String anotherString) {1175 int len1 = count;1176 int len2 = anotherString.count;1177 int n = Math.min(len1, len2);1178 char v1[] = value;1179 char v2[] = anotherString.value;1180 int i = offset;1181 int j = anotherString.offset;1183 if (i == j) {1184 int k = i;1185 int lim = n + i;1186 while (k < lim) {1187 char c1 = v1[k];1188 char c2 = v2[k];1189 if (c1 != c2) {1190 return c1 - c2;1191 }1192 k++;1193 }1194 } else {1195 while (n-- != 0) {1196 char c1 = v1[i++];1197 char c2 = v2[j++];1198 if (c1 != c2) {1199 return c1 - c2;1200 }1201 }1202 }1203 return len1 - len2;1204 }
When one of the strings is a prefix of another, the performance of compareTo() is worse as it still needs to determine the lexicographical ordering while equals() won't worry any more and return false immediately.
In my opinion, we should use these two as they were intended:
equals() to check for equality, and
compareTo() to find the lexical ordering.
equals() checks whether two strings are equal or not.It gives boolean value.
compareTo() checks whether string object is equal to,greater or smaller to the other string object.It gives result as :
1 if string object is greater
0 if both are equal
-1 if string is smaller than other string
eq:
String a = "Amit";
String b = "Sumit";
String c = new String("Amit");
System.out.println(a.equals(c));//true
System.out.println(a.compareTo(c)); //0
System.out.println(a.compareTo(b)); //1
There are certain things which you need to keep in mind while overriding compareTo in Java e.g. Compareto must be consistent with equals and subtraction should not be used for comparing integer fields as they can overflow. check Things to remember while overriding Comparator in Java for details.
equals can take any Object as a parameter but compareTo can only take String.
when cometo null,compareTo will throw a exception
when you want to know where the diff happen,you can use compareTo.
This is an experiment in necromancy :-)
Most answers compare performance and API differences. They miss the fundamental point that the two operations simply have different semantics.
Your intuition is correct. x.equals(y) is not interchangeable with x.compareTo(y) == 0.
The first compares identity, while the other compares the notion of 'size'. It is true that in many cases, especially with primitive types, these two co-align.
The general case is this:
If x and y are identical, they share the same 'size': if x.equals(y) is true => x.compareTo(y) is 0.
However, if x and y share the same size, it does not mean they are identical.
if x.compareTo(y) is 0 does not necessarily mean x.equals(y) is true.
A compelling example where identity differs from size would be complex numbers. Assume that the comparison is done by their absolute value. So given two complex numbers: Z1 = a1 + b1*i and Z2 = a2 + b2*i:
Z1.equals(z2) returns true if and only if a1 = a2 and b1 = b2.
However Z1.compareTo(Z2) returns 0 for and infinite number of (a1,b1) and (a2,b2) pairs as long as they satisfy the condition a1^2 + b1^2 == a2^2 + b2^2.
Equals can be more efficient then compareTo.
If the length of the character sequences in String doesn't match there is no way the Strings are equal so rejection can be much faster.
Moreover if it is same object (identity equality rather then logical equality), it will also be more efficient.
If they also implemented hashCode caching it could be even faster to reject non-equals in case their hashCode's doesn't match.
String.equals() requires invoking instanceof operator while compareTo() requires not. My colleague has noted large performance drop-down caused by excessive numbers of instanceof calls in equals() method, however my test has proved compareTo() to be only slightly faster.
I was using, however, Java 1.6. On other versions (or other JDK vendors) the difference could be larger.
The test compared each-to-each string in 1000 element arrays, repeated 10 times.
String s1 = "a";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints -2 and false
String s1 = "c";
String s2 = "a";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints 2 and false
String s1 = "c";
String s2 = "c";
System.out.println(s1.compareTo(s2));
System.out.println(s1.equals(s2));
This prints 0 and true
equals returns boolean if and only if both strings match.
compareTo is meant to not just tell if they match but also to tell which String is lesser than the other, and also by how much, lexicographically. This is mostly used while sorting in collection.
Equals -
1- Override the GetHashCode method to allow a type to work correctly in a hash table.
2- Do not throw an exception in the implementation of an Equals method. Instead, return false for a null argument.
3-
x.Equals(x) returns true.
x.Equals(y) returns the same value as y.Equals(x).
(x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.
Successive invocations of x.Equals(y) return the same value as long as the object referenced by x and y are not modified.
x.Equals(null) returns false.
4- For some kinds of objects, it is desirable to have Equals test for value equality instead of referential equality. Such implementations of Equals return true if the two objects have the same value, even if they are not the same instance.
For Example -
Object obj1 = new Object();
Object obj2 = new Object();
Console.WriteLine(obj1.Equals(obj2));
obj1 = obj2;
Console.WriteLine(obj1.Equals(obj2));
Output :-
False
True
while compareTo -
Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
It returns -
Less than zero - This instance precedes obj in the sort order. Zero - This instance occurs in the same position in the sort order as obj. Greater than zero - This instance follows obj in the sort order.
It can throw ArgumentException if object is not the same type as instance.
For example you can visit here.
So I suggest better to use Equals in place of compareTo.
equals:
required for checking equality and restricting duplicates. Many classes of Java Library use this in case they wanted to find duplicates. e.g. HashSet.add(ob1) will only add if that doesn't exist. So if you are extending some classes like this then override equals().
compareTo:
required for ordering of element. Again for stable sorting you require equality, so there is a return 0.
"equals" compare objects and return true or false and
"compare to" return 0 if is true or an number [> 0] or [< 0] if is false
here an example:
<!-- language: lang-java -->
//Objects Integer
Integer num1 = 1;
Integer num2 = 1;
//equal
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
//New Value
num2 = 3;//set value
//diferent
System.out.println(num1.equals(num2));
System.out.println(num1.compareTo(num2));
Results:
num1.equals(num2) =true
num1.compareTo(num2) =0
num1.equals(num2) =false
num1.compareTo(num2) =-1
Documentation Compare to: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html
Documentation Equals : https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)
Here one thing is important while using compareTo() over equals() that compareTo works for the classes that implements 'Comparable' interface otherwise it will throw a NullPointerException. String classes implements Comparable interface while StringBuffer does not hence you can use "foo".compareTo("doo") in String object but not in StringBuffer Object.
I believe equals and equalsIgnoreCase methods of String return true and false which is useful if you wanted to compare the values of the string object, But in case of implementing compareTo and compareToIgnoreCase methods returns positive, negative and zero value which will be useful in case of sorting.