Related
Specifically, in the case of object reference equality, what does the == operator do?
Does the comparison return true if the references evaluate to the same object address at the time of comparison? Or does it utilize the hashCode value of the two references to determine if the objects are the same?
To be very specific here, I would like to know what data structures managed by the JVM are referenced by the == operation for reference comparison. Does == rely on the OOP to perform reference comparison?
Unfortunately for me, the JLS does not define how the == operator must work. The Java API docs do not mention what == is supposed to do (they're for classes, right?)
PS: I was a bit intrigued by this question on hashcode uniqueness, and would prefer to know how the Sun JVM (or OpenJDK) implements the == operator.
The == operator just compares the references.
References in the JVM are just a standard object pointer. This works out to a single 32bit or 64bit integer value (depending on platform).
When you compare two object references, you're really just comparing two 32bit or 64bit integers, and if they're the same, you'll equate to equal. The integer values are a location in memory.
Because a reference is just a number, a reference comparison comes down to just comparing two numbers. No hash is needed.
The == operator compares object references to see if they are identical, i.e. they refer to the same object in memory.
The equals() method compares object references to see if they are equivalent, though not necessarily identical. The default implementation of equals() uses the == operator, but it often makes sense to override this behavior. For example, you might want two BankAccount references to be considered equivalent if they have the same account number, even if they are completely different objects.
The == operator returns true if the objects are the same object. There is not access to hashCode() or equals() here.
Try this to confirm:
public class Test {
static void testEqualEqual(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0 == I1)))
throw new AssertionError();
}
static void testEqual(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0.equals(I1))))
throw new AssertionError();
}
static void testHash(Integer I0, Integer I1, boolean IsEquals) {
if(!(IsEquals == (I0.hashCode() == I1.hashCode())))
throw new AssertionError();
}
public static void main(String ... args) {
testEqualEqual( 1, 1, true);
testEqualEqual(2000, 2000, false);
testEqual( 1, 1, true);
testEqual(2000, 2000, true);
testHash( 1, 1, true);
testHash(2000, 2000, true);
System.out.println("Done");
}
}
To understand this, you should know first that the number number 255 will be cached when autoboxed. This means that Integer of 1 is always the same object but Integer of 2000 will always be different object.
This experiment shows that '==' return true when the objects are the same. In case of '1' they are the same number and it returns true. But in case of '2000' autoboxed to be different objects so it returns false.
The experiment also shows that '==' does not use equals() or hashCode().
Hope this helps.
This question already has answers here:
Java: Use hashCode() inside of equals() for convenience?
(7 answers)
Closed 7 years ago.
Let's say we have a hashcode() function, which will then be used inside our equals() method to determine the equality of two objects. Is this an allowed/accepted approach?
Assume that we use a simple implementation of a hash code. (For example a few instance variables multiplied by prime numbers.)
This is a terrible way to check for equality, mostly since Objects don't have to be equal to return the same hashcode.
You should always use the equals method for this.
The general rule is:
If the equals method returns true for Objects a and b, the hashCode
method must return the same value for a and b.
This does not mean, that if the hashCode method for a and b returns
the same value, the equals method has to return true for these two
instances.
for instance:
public int hashCode(){
return 5;
}
is a valid, though be it inefficiënt, hashcode implementation.
EDIT:
to use it within an equals method would be something like this:
public class Person{
private String name;
public Person(String name){ this.name = name;}
public String getName(){ return this.name;}
#Override
public boolean equals(Object o){
if ( !(o instanceof Person)){ return false;}
Person p = (Person)o;
boolean nameE = this.name == null ? p.getName() == null : this.name.equals(p.getName());
boolean hashE = nameE ? true : randomTrueOrFalse();
// the only moment you're sure hashE is true, is if the previous check returns true.
// in any other case, it doesn't matter whether they are equal or not, since the nameCheck returns false, so in best case, it's redundant
return nameE && hashE;
}
#Override
public int hashCode(){
int hash = generateValidHashCode();
return hash;
}
}
It is a very bad practice. Hashes are supposed to have a minimal amount of collisions, but usually you have more possibilities for objects than the amount of possible hashes and because of the pigeonhole principle a few distinct objects must have the same hash.
When comparing hashes, you have a certain chance of getting "false positives".
Actually, it is not a bad idea!
But make sure you use this method to determine inequality, not equality. Hashing code may be faster than checking equality, especially when hashcode is stored (for example in java.lang.String).
If two object have different hashcodes they must be different, else they may be the same. For example you may use this method as the following
Object a, b;
if(a.hashCode() == b.hashCode()){
if(a.equals(b)) return true;
}
return false;
Be aware that in some cases code above may be slower than using only equals(), especially when in most cases a does equal b.
From documentation of Object.java:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
Don't do this
While it is correct that you need to override equals() and hashCode() in pairs, having the same hash is not the same as having the same values.
Put some effort into really thinking the equality thing through. Don't shortcut here it will bite you later.
This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed 7 years ago.
I am not exactly sure why the hashCode() method is returning the same value. Can someone provide more detailed explanation of this?
Source code (Java):
public class Equality {
public static void main(String [] args)
{
String str = "String";
String strOne = new String("String");
System.out.println(str == strOne);
System.out.println(str.equals(strOne));
System.out.println(str.hashCode());
System.out.println(strOne.hashCode());
}
}
From the Javadoc :
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently
return the same integer, provided no information used in equals
comparisons on the object is modified. This integer need not remain
consistent from one execution of an application to another execution
of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must
produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method
on each of the two objects must produce distinct integer results.
However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hash tables.
Basically, a.equals(b) => a.hashCode() == b.hashCode() so two identical strings will surely have the same hashCode.
It seems to me that the behaviour you were expecting is the one of ==, but it clearly is not. == is the strongest equality in Java, because it compares the location in memory of two objects. equals comes just after it, it is a logical equality, two objects can be equal even if they have different memory locations. The hashCode has the weakest properties, quoted above.
This should help your understanding. According to the Java 7 docs for String.hashCode() (I believe Java 6/8 should be similar or identical):
public int hashCode()
Returns a hash code for this string. The hash code for a String object is computed as
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
using int arithmetic, where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation. (The hash value of the empty string is zero.)
The hasCode() method applied on the value of String which is "String" both case.
Although you have created two reference of String type like this -
String str = "String";
String strOne = new String("String");
But the hashCode() use the value assigned with the reference (str and strONe). Thats why the two hashCode() are equals.
Look at the hashCode() method of String class -
public int hashCode() {
int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
and value is declared like this -
private final char value[];
Consider two references of type Integer that call the static factory method valueOf as shown below:-
Integer a = Integer.valueOf("10");
Integer b = Integer.valueOf("10");
Considering that Integer is immutable, is it ok to compare a and b using == instead of using equals method. I am guessing that the valueOf method makes sure that only one instance of Integer with the value 10 is created and a reference to this instance is returned for every Integer created with a value 10.
In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?
Edit:
The Integer class was used just as an example. I am aware thar Intgers upto 127 will return true if they are compared using ==. What i need to know is that when l create my own immutable class, say MyImmutable with a method create() that will ensure that no duplicate MyImmutable objects are created, will it be ok if I compare 2 MyImmutable references created using the create method by using == instead of equals.
No, that's not safe in general. The == operator compares the references, not the values.
Using == happens to work for integers between -128 and 127, but not for other integers. The following code demonstrates that == won't always work:
Integer a = Integer.valueOf(10);
Integer b = Integer.valueOf(10);
System.out.println(a == b);
true
Integer c = Integer.valueOf(1000);
Integer d = Integer.valueOf(1000);
System.out.println(c == d);
false
See it working online: ideone
The explanation for this behaviour lies in the implementation of Integer.valueOf:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
source
Not also that the standard requires that boxing integers for small inputs (-128 to 127) gives objects with equal references.
5.1.7 Boxing Conversion
If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
However the standard makes no such guarantees for integers outside this range.
In general, is it ok to compare two references of an immutable class that are created using a call to the same static factory method by using == instead of equals?
As shown above, it won't work in general. But if you ensure that two immutable objects with the same value always have the same reference, then yes, it could work. However there are some rules you must follow carefully:
The constructor must not be public.
Every object you create via the static method must be cached.
Every time you are asked to create an object you must first check the cache to see if you have already created an object with the same value.
== and equals() is fundamentally different.
You should read this post for more details:
Difference between Equals/equals and == operator?
It has nothing to do with immutable objects.
If your factory method returns the same object for equal inputs, it's safe to compare them with ==. For example String.intern works this way. Enums are also could be compared with ==. But Integer.valueOf returns the same object only for -128 ... 127 range (in default configuration).
Integer.valueOf(127) == Integer.valueOf(127)
but
Integer.valueOf(128) != Integer.valueOf(128)
Generally speaking you should use equals method to compare any objects. Operator == could be used to improve performance, when there are small number of different values for object. I wouldn't recommend to use this method, unless you are 100% sure in what you are doing.
Immutability and equality do not necessarily have something to do with each other. == compares for reference equality, that means, it compares if both variables point to the very same instance of the object. Equality means that both objects share the same value. Immutability now means that you can not alter an object after its construction.
So, you might have two immutable obejcts, that represents the same value (meaning, they are equals so that a.equals(b) returns true) but that are not the same instance.
I have a little example for you here:
public class MyPoint {
private int x;
private int y;
public MyPoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof MyPoint))
return false;
MyPoint p = (MyPoint) obj;
return this.x == p.x && this.y == p.y;
}
/**
* #param args
*/
public static void main(String[] args) {
MyPoint p = new MyPoint(2, 2);
MyPoint q = new MyPoint(2, 2);
MyPoint r = q;
System.out.println(p == q);
System.out.println(p == r);
System.out.println(q == r);
System.out.println(p.equals(q));
System.out.println(p.equals(r));
System.out.println(q.equals(r));
}
}
The output is:
false
false
true
true
true
true
MyPoint is immutable. You can not change its values / its state after is has been initialized. But, as you can see, two objects of myPoint might be equal, but they might not be the same instance.
I think what you have in mind is some kind of flyweight pattern, where only one object exists for every possible state of the object. Flyweight also means commonly that those obejcts are immutable.
They are not the same object, so == will not be true. With objects, be safe and use equals().
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.