Same object different hash code? - java

class Rational {
int num = 0;
int denom = 0;
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
public static void main(String[] args) {
Rational r1 = s.new Rational(1, 1);
Rational r2 = s.new Rational(1, 1);
System.out.println(r1.hashCode());
System.out.println(r2.hashCode());
}
I have two of the same objects, but they have different hashCode. Why is that?
I tried overriding the .equal method in Rational so r1.equals(r2) == true. But they still produce different Java hashCode.

They are not the same object; they are two different objects with the same value. Just because there's another Jeroen Vannevel in the world doesn't mean it's me.
hashCode() is not linked to equals(): they both have a contract they have to adhere to and they are related but they do not directly influence eachother. That's why you should always override both of these methods and not just one.

I have two of the same objects
"Same" usually means, literally, one object. Here what you have are equivalent objects.
...but they have different hashCode. Why is that?
Because you haven't overridden hashCode to replace the default implementation. Overriding equals doesn't change hashCode (you almost always have to override both if you override equals).
The hashCode documentation says this about the default implementation in Object:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
So you'll get distinct integers (usually) for different instances, even if they're equivalent, unless you replace hashCode.
In your case, you could do this:
#override
public int hashCode() {
return this.num ^ this.denom;
}
...and have a reasonable hashCode for Rational (be sure to override equals as well), but there are lots of other ways. Just stick to the contract:
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.

Related

difference between equals() and hashCode()

I want a brief definition about the equals() , "==" and hashCode(). If i run following code means the output will be "true false 2420395 2420395". But i had understand that equals() method compares the string and "==" compares the reference. But in output the hashCcode() method prints the reference number for both strings as same then why the "==" returns "false".
String str = "Name";
String str1 = new String("Name");
if (str.equals(str1))
System.out.println("true");
else
System.out.println("false");
if (str == str1)
System.out.println("true");
else
System.out.println("false");
System.out.println(str.hashCode());
System.out.println(str1.hashCode());
The equals() and hashCode() methods prove to be very important, when objects implementing these two methods are added to collections. If implemented incorrectly it might screwed up your life.
equals() : This method checks if some other object passed to it as an argument is equal the object in which this method is invoked. It is easy to implement the equals() method incorrectly, if you do not understand the contract. Before overriding this method, following “properties” need to keep in mind -
Reflexive: o1.equals(o1) - which means an Object (e.g. o1) should be equal to itself
Symmetric: o1.equals(o2) if and only o2.equals(o1)
Transitive: o1.equals(o2) && o2.equals(o3) implies that o1.equals(o3) as well
Consistent: o1.equals(o2) returns the same as long as o1 and o2 are unmodified
null comparison : !o1.equals(null) - which means that any instantiable object is not equal to null. So if you pass a null as an argument to your object o1, then it should return false.
Hash code value: o1.equals(o2) implies o1.hashCode() == o2.hashCode() . This is very important. If you define a equals() method then you must define a hashCode() method as well. Also it means that if you have two objects that are equal then they must have the same hashCode, however the reverse is not true
From java source code
*
* #param obj the reference object with which to compare.
* #return {#code true} if this object is the same as the obj
* argument; {#code false} otherwise.
* #see #hashCode()
* #see java.util.HashMap
*/
public boolean equals(Object obj) {
return (this == obj);
}
hashCode(): This method returns a hashCode() value as an Integer and is supported for the benefit of hashing based java.util.Collection classes like Hashtable, HashMap, HashSet etc. If a class overrides the equals() method, it must implement the hashCode() method as well.Before overriding this method, you need to keep in mind
Whenever hashCode() method is invoked on the same object more than once during an execution of a Java program, this method must consistently return the same result. The integer result need not remain consistent from one execution of the program to the next execution of the same program.
If two objects are equal as per the equals() method, then calling the hashCode() method in each of the two objects must return the same integer result. So, If a field is not used in equals(), then it must not be used in hashCode() method.
If two objects are unequal as per the equals() method, each of the two objects can return either two different integer results or same integer results (i.e. if 2 objects have the same hashCode() result does not mean that they are equal, but if two objects are equal then they must return the same hashCode() result).
As per java source code
As much as is reasonably practical, the hashCode method defined by java.lang.Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer)
hashCode() does not return the object's reference, but a hash of the object, computed in some way. == does not compare objects using the value of hashCode() but, as you correctly say, by the value of the objects' references.
.equals() compares the actual content of the string.
The "==" operator compares if the two objects are the same reference in memory. If you were to do str = str1;, then the double-equals operator would return true because they point to the same reference in memory.
hashCode() returns a hash of the object in an arbitrary manner. The value returned will always be unique as long as the method is not overridden in some way. If .equals() returns true, the hash code should be the same.
You can read the hashCode documentation. In a few words it says that if (obj1.equals(obj2) is true then obj1.hashCode()==obj2.hasCode() must be true to be a valid implementation.
Note that it does not mean that two different objects cannot share the same hash code. Actually, this example is a valid (but awful) implementation of the method:
class MyClass {
public int hashCode() {return 0;}
}
equals() and hashCode() are different methods and hashCode method should not be used to check if two object references are same.
Reason: hashCode just returns int value for an Object, even two different objects can have same hashCode integer. The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal.
equals() checks if the two object references are same. If two objects are equal then their hashCode must be the same, but the reverse is not true.
As other said '==' compares references. But the two methods are just methods doing something which can be overridden.
Every method does something. If you want to know what it exactly does and what is its meaning you need to read the documentation.
You may override those methods in anyway you want. But please note that you must follow JAVA documentation for these two methods. Because they are used by other classes. For example equals() is used while you try find an object in a list and .hashCode() is used in some hashtable classes provided by JAVA class library.
equals() only compare string it's does not check reference of string
but '==' check reference and data both
in 1st case String str = "Name"; only one object is created but in
2nd case Two object is created
String str1 = new String("Name");
then reference are not same of both string that means it returns false

Equal object in Java

So this is from Head First Java (page 563)
The default behaviour of hashCode() is to generate a unique integer
for each object on the heap. So if you don’t override hashCode() in a
class, no two objects of that type can EVER be considered equal.
But a simple Test will disprove this I think.
public class Song {
private String name;
public Song(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object obj) {
Song objectSong = (Song) obj;
return this.getName().equals(objectSong.getName());
}
}
Well this will return true:
Song songA = new Song("A","B");
Song songB = new Song("A","C");
System.out.println(songA.equals(songB));
Am I missing something? What is it that the book is trying to tell me?
The default behaviour of hashCode() is to generate a unique integer
for each object on the heap. So if you don’t override hashCode() in a
class, no two objects of that type can EVER be considered equal.
You're misinterpreting. The author isn't saying that a method (that's all equals and hashCode are) can't return true for two different objects. They're saying that semantically two objects should not be considered equal if the result of their hashCode isn't equal. They are describing how hashCode should be used. If you use it differently, you may get weird and unexpected results.
You need to override hashcode so that the class behaves as expected with hashcode based collections (and anything else).
For example what happens if you put your song in a HashSet, and then try to put another one in ?
You should always override Hashcode if you override equals, and vice versa. Make sure they are consistent.
(josh bloch effective java, is a good starting point)
In Java, every object has access to the equals() method because it is
inherited from the Object class. However, this default implementation
just simply compares the memory addresses of the objects. You can
override the default implementation of the equals() method defined in
java.lang.Object. If you override the equals(), you MUST also override
hashCode(). Otherwise a violation of the general contract for
Object.hashCode will occur, which can have unexpected repercussions
when your class is in conjunction with all hash-based collections.
Source: http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20 (take a look at it, it has good examples).
Conclusion: you only need to override equals for a simple comparison. However, you SHOULD also override hashCode for other aspects, such as hash based collections.

Does the return value of hashCode() for enum values change with runtime

I am using overridden hashCode() in one of my objects (instance of A) to generate a unique integer ID for that object. The uniqueness depends only on elements(instances of B) in a ArrayList (I).
Following is the definition of I:
public class I extends ArrayList<B> {
//object of this class will iterate over this array
private B[] arrayOfB;
//other methods and variable to do something
...
}
Definition of class B
public class B {
private SomeEnum type;
private Object value; //this can be Integer, String, or some object defined by me
//getters for both private variables
...
}
Definition of class A
public class C implements Iterable {
private I myIterable;
#Override
public int hashCode() {
int result = 17;
for(B b: myIterable) {
result = 31 * result + b.getType().hashCode();
result = 31 * result + b.getValue().hashCode();
}
return result;
}
//other methods for this class
...
}
As you can see I iterate over all objects in myIterable and construct the final hash. The result depends on type and value contained in each b in myIterable. What I have noticed is that this value changes with different runs of program and this creates a problem as the program is creating duplicate objects.
I can implement the hashCode() for the concerned enumerations but I was wondering if there is some other way to handle this. Following are my questions:
Can the hashCode() of equal strings change between runtime?
Can the hashCode() of same enum values change between runtime?
NOTE: I am aware that my implementation of A.hashCode() will return different values of hash depending on order of b in myIterable, which is not desired. I am fixing it so that order is not important.
So do you have different results regardless of the order (for example, when these hashCodes are calculated in isolation)?
From hashCode documentation http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29 :
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.
It looks like theoretically it is possible. However, I think it would be non-standard implementation. Here is the actual source code (openjdk7):
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/String.java#String.hashCode%28%29
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/Enum.java#Enum.hashCode%28%29
There is a difference between what can be done, and what works.
You could subclass (as you have done) and make hashCode() return different values based on the current field settings. That's actually a good thing in one sense of the issue. If the two objects differ by value, then they should return different hashCodes.
However, what you are doing is having one object change its equality to itself. You don't have two objects that become equal, you have one object that decides it isn't equal to "its old self" and possibly won't be equal to its future self.
That's just plain nonsense in the Java world, as no collection is going to monitor its constituents for changes in how they equal themselves (a requirement for some collections, such as maps).
In short, hashCode() provides a means for changing how equality is determined, but not a means for creating a new mathematical property that doesn't follow the definition of equality. You need to maintain A = A for the entire duration of your program execution (and in some cases, even longer).

Should 2 Java objects of different classes ever be equal?

I'm trying to write some generic code to define class equality and hashcodes based on a list of fields. When writing my equals method, I was wondering if, based on Java convention, it should ever be possible for two object of different to be equal. Let me give some examples;
class A {
int foo;
}
class B {
int foo;
}
class C extends A {
int bar;
}
class D extends A {
void doStuff() { }
}
...
A a = new A(); a.foo = 1;
B b = new B(); b.foo = 1;
C c = new C(); c.foo = 1; c.bar = 2;
D d = new D(); d.foo = 1;
a.equals(b); //Should return false, obviously
a.equals(c);
c.equals(a); //These two must be the same result, so I'd assume it must be false, since c cant possible equal a
a.equals(d); //Now this one is where I'm stuck.
I see no reason that in the last example the two shouldn't be equal, but they do have different classes. Anyone know what convention dictates? And if they would be equal, how should an equals method handle that?
Edit: if anyone's interested in the code behind this question, see: https://gist.github.com/thomaswp/5816085 It's a little dirty but I'd welcome comments on the gist.
They could be, but it's typically very difficult to maintain the symmetric and transitive properties of equality in that case. At least while having a useful/intuitive definition of equality.
If you allow a subclass to consider itself equal to an instance of the superclass, then the superclass needs to consider itself equal to an instance of the subclass. Which means that you'll be encoding specific knowledge about the subclass (all possible subclasses?) in the superclass, and downcasting as needed, which isn't very clean.
Or, you do the comparison purely with fields contained in A, and don't override equals() at all. This fixes the above, but has the problem that two instances of C with different values of bar would be considered equal, which is probably not what you want.
Or, you override in C, and compare bar if the other object is an instance of C, but otherwise don't for an instance of A, you have another problem. c1.equals(c2) would be false, but c1.equals(a) would be true, as would c2.equals(a) and so a.equals(c2). This breaks transitivity (since c1 == a and a == c2 implies c1 == c2).
In summary, it's theoretically possible but you would have to cripple your equals implementation to do so. And besides, the runtime class is a property of an object just as much as bar is, so I'd expect objects with different concrete classes to be not equal to each other anyway.
First note: when you override .equals(), you absolutely MUST override .hashCode() as well, and obey the defined contract. This is no joke. If you do not obey THAT, you are doomed to encounter problems.
As to handling equality between different classes inheriting one another, if all these classes have a common member, this can be done as such:
#Override
public int hashCode()
{
return commonMember.hashCode();
}
#Override
public boolean equals(final Object o)
{
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof BaseClass))
return false;
final BaseClass other = (BaseClass) o;
return commonMember.equals(other.commonMember); // etc -- to be completed
}
Also remember that you need to follow these rules in order to correctly implement the equals method.
Reflexive : Object must be equal to itself.
Symmetric : if a.equals(b) is true then b.equals(a) must be true.
Transitive : if a.equals(b) is true and b.equals(c) is true then c.equals(a) must be true.
Consistent : multiple invocation of equals() method must result same value until any of properties are modified. So if two objects are equals in Java they will remain equals until any of there property is modified.
Null comparison : comparing any object to null must be false and should not result in NullPointerException. For example a.equals(null) must be false, passing unknown object, which could be null, to equals in Java is is actually a Java coding best practice to avoid NullPointerException in Java.
As Andrzej Doyle rightly said, it becomes difficult to implement the Symetric and Transitive property when it's spread across multiple classes.
Object.equals() is required to be reflexive, symmetric, transitive, consistent across multiple invocations, and x.equals(null) must be false. There are no further requirements beyond that.
If equals() for a class you define does all of those things, then it's an acceptable equals() method. There is no answer to the question of how fine-grained it should be other than the one you provide yourself. You need to ask yourself: Which objects to I want to be equal?
Note, however, that you should have a good reason for making a.equals(b) true when a and b are instances of different classes, as that can make it tricky to implement a correct equals() in both classes.
This question seems to me to indicate a muddy architecture. In theory, if you want to implement .equals such that you compare only specific members of the two instances you can do this, but whether this is a good idea really depends on just what purpose these classes are intended to serve (and even then I think there are better approaches).
Are these objects, more or less, just intended to be nothing more than bags of data? If so, perhaps you should create a separate comparison class that determines whether the two objects are "equivalent enough" for the purposes you need, rather than force the objects themselves to care about some alien, unrelated class. I'd be concerned if my code were concerning itself with potentially unrelated objects just because I thought it might be a good idea for them to know about each other due to temporary convenience. Also, as Andrzej mentioned, it's very problematic for a parent class to know or care about specific implementation details of derived classes. I've seen first-hand how this causes problems both subtle and egregious.
Are the objects "doers" rather than data storage? Since your subclass D implements a method then this indicates that it's more than just a bag of data... and in this case, philosophically, I can't see how it would be a good idea to consider A and D equal based merely on a set of value fields. Compare the fields, yes. Consider them equal or equivalent? No. This sounds like a maintainability nightmare in the long haul.
Here's an example of what I think would be a better idea:
class A implements IFoo{
private int foo;
public int getFoo(){ return foo; }
}
class B implements IFoo{
private int foo;
public int getFoo(){ return foo; }
}
class CompareFoos{
public static boolean isEquivalent(IFoo a, IFoo b){
// compare here as needed and return result.
}
}
IFoo a = new A();
IFoo b = new B();
boolean result = CompareFoos.isEquivalent(a, b);
To some extent it depends on what you want the code to do. As long as you are clear what the equals method will compare then I don't see a problem necessarily. I think the problem really comes when you start making lots of sub-classes (e.g. Class E). There's a danger than that one of the sub-classes won't follow the contract so you could end up with
a.equals(e) --> true
e.equals(a) --> false
which would result in strange behaviour.
Personally I try to avoid equals comparing two different classes and returning true but I have done it a couple of times where the whole class hierarchy was under my control and final.
Consider this example -
abstract class Quadrilateral{
Quadrilateral(int l, int w){
length=l;
width=w;
}
private int length, width;
}
class Rectangle extends Quadrilateral{
Rectangle(int l, int w){super(l,w);}
}
class Square extends Quadrilateral{
Square(int l){super(l, l);}
}
Square s = new Square(3);
Rectangle r = new Rectangle(3,3);
r.equals(s);//This should be true because the rectangle and square are logically the same.
So yes, there are cases where two different classes can be equal. Though clearly this is not common.
No.
Set<Parent> p = new HashSet<>();
p.insert(new Parent(1));
p.insert(new Child(1));
Supposing those two instances are equals, does p contain a Child? Very unclear. More fun:
class Parent {
public int foo = 0;
void foo() {
foo = 1;
}
}
class Child extends Parent {
#Override
void foo() {
foo = 2;
}
}
Set<Parent> set = new HashSet<>();
for(Parent parent : set) {
parent.foo();
System.out.println(parent.foo); // 1 or 2?
}
I challenge you to know what p's element contains without spending more than 1 minute on the Javadoc pages for Set, HashSet, or equals.
The short answer is that in very limited cases (e.g. Integer and Long) it is OK for two objects of different classes to be equal, but it is so hard to pull off correctly that it is generally discouraged. It's hard enough to ensure that you create an equals() method that is Symmetric, Reflexive, and Transitive, but on top of that you should also:
create a hashCode() method that is consistent with equals()
create a compareTo() method that is consistent with equals()
further ensure that the compareTo() method is well behaved
Failure to do that can cause problems with using the objects in Sets, Trees, Hashes, and Sorted Lists.
There's a good article on the the topic of equals() based on part of Josh Bloch's book Effective Java but even that only covers equals(). The book goes into much greater detail, especially about how the problem becomes serious quickly once you start using the objects in collections.
It depends what you need, as #andrzeg said.
One additional thing. Do you want a.equals(d) to be true, but d.equals(a) to be false? when coding you will probably be using instanceof which may or may not be what you want.
I think that this question can be reduced to whether to use instanceof or getClass() in equals() implementation.
If D derives A and your inheritance hierarchy is right then indeed D IS A. It is logical to treat D as any other A and therefore you should be able to check D for equality as you would any other A.
Here is a link where Josh Bloch explains why he favors the instanceof approach.
http://www.artima.com/intv/bloch17.html

Why Java does not support Equality comparison on the Lines of Comparator?

Java provides way to define comparison of object outside scope Object using Comparator.
Now my questions is why java does not allow do same for equals() and hashcode().
Now each collection contains() method can easily use this external equality provider to check objects are equal.
Guava has the Equivalence class, which does pretty much what you are asking for.
You can even wrap an Object in an Equivalence to decorate an Object with a better hashCode() equals() implementation (e.g. if you want to use an Object with a bad equals() hashCode() as a Map key but don't have access to the sources)
Here's an example: arrays don't have proper implementations of equals() and hashCode(), but here's an Equivalence for char arrays:
private static final Equivalence<char[]> CHAR_ARRAY_EQUIV = new Equivalence<char[]>(){
#Override
protected boolean doEquivalent(char[] a, char[] b) {
return Arrays.equals(a, b);
}
#Override
protected int doHash(char[] chars) {
return Arrays.hashCode(chars);
}
};
Sample code:
final char[] first ={'a','b'};
final char[] second ={'a','b'};
Assert.assertFalse(first.equals(second));
Assert.assertFalse(first.hashCode() == second.hashCode());
final Wrapper<char[]> firstWrapped = CHAR_ARRAY_EQUIV.wrap(first);
final Wrapper<char[]> secondWrapped = CHAR_ARRAY_EQUIV.wrap(second);
Assert.assertTrue(firstWrapped.equals(secondWrapped));
Assert.assertTrue(firstWrapped.hashCode() == secondWrapped.hashCode());
Comparator interface is used to compare objects while sorting collections, and its compare() method returns an "int", means, comparision ends with an int value, which can be used to indicate object's place in a sorted collection.
contains() calls equals() method for each instance in a collection in order to find out whether two instances are equal according to equals- contract.
equals and hashCode are concepts that don't change for a given Object. Only the implementor knows what values should be used according to the rules for these methods. Once he decided about those they define the identy of the object and thus should not be changed ever.
Comparasion on the other hand can be highly dependent on the context. You can define a "natural" order by implementing Comparable. But this can't change for different contexts. Say you have a list of Contacts that can be sorted by last name, first name, zip code, city... You can easily do this by providing separate Comparators (or a parametrized Comparator). But it is not inherent to the object itself so it should be a class of its own (it could be implemented as static inner class, depending on your code conventions).

Categories