Object's Hashcode is not a physical memory location of the object located in heap. Its a digest of the data stored in an instance of the class into a single hash value (a 32-bit signed integer). (Source wiki)
But in case of hashing(HashSet, HashMap etc), we need to override hashcode and equals method
Yes, until and unless you're using your class instance as a key in any map implemented classes.
Now consider your given scenrio :
@override
int hashcode(){
return id*31;
}
Nothing will happen but you end up adding different objects in to your map or set.
Important Contract :
There is a contract between object hashcode
and equals
method saying that, when you override equals
you must override hascode()
and vice versa inorder to uniformly distribute the object among the buckets.
Be Carefull !!
// The worst possible legal hash function - never use!
@Override
public int hashCode() {
return 42;
}
(Source Effective Java)
It’s very much legal because it ensures that equal objects have the same hash code. It’s atrocious because it ensures that every object has the same hash code. Therefore, every object hashes to the same bucket, and hash tables degenerate to linked lists. Programs that should run in linear time instead run in quadratic time. For large hash tables, this is the difference between working and not working.
For your clarification :
Consider this, Bellow is my class and here I'm defining the contract between equals and hascode saying that two objects having same roll and name must be identical.
public class MyClass {
private int roll;
private String name;
private String subject;
public MyClass(int roll, String name, String subject) {
this.roll = roll;
this.name = name;
this.subject = subject;
}
@Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
MyClass myclass = (MyClass) object;
if (this.roll == myclass.getRoll()
&& this.name == myclass.getName()) {
result = true;
}
}
return result;
}
@Override
public int hashCode() {
int hash = 17;
hash = 31 * this.roll;
hash = 31 * hash + this.name.hashCode();
return hash;
}
public static void main(String args[]) {
MyClass obj1 = new MyClass(1, "A", "Math");
MyClass obj2 = new MyClass(1, "A", "Phy");
MyClass obj3 = new MyClass(1, "B", "Chem");
System.out.println("obj1.equals(obj2) : "+obj1.equals(obj2)); // true. As both the objects have the same roll & name
System.out.println("obj1 == obj2 : "+(obj1 == obj2)); // false. because two are references of different instance.
Set<MyClass> set = new HashSet<MyClass>();
set.add(obj1);
set.add(obj2);
System.out.println("set :"+set.size()); // 1 object
for(MyClass cls:set){
System.out.println(cls); //i.e [1 A Math]. It'll not replaced by the 2nd one.
}
Map<MyClass,String> map= new HashMap<MyClass,String>();
map.put(obj1,"IN");
map.put(obj2,"US");
System.out.println("map :"+map.size());// 1 object
for (Map.Entry<MyClass, String> entry : map.entrySet()){
System.out.println(entry.getKey() + " : " + entry.getValue()); // [1 A Math : US]. here you may notice the key remains same but the value will be replaced.
}
}
public int getRoll() {
return roll;
}
public String getName() {
return name;
}
public String getSubject() {
return subject;
}
@Override
public String toString(){
return ""+roll+" "+name+" "+subject;
}
}
Note: Whenever you're creating an object using new
keyword, each time it'll create a different object in the heap no matter the contents in them are same or not.
hashcode
may return the a hash representing the memory location, but it's quite legal to return whatever you want, so long as you maintain the contract betweenequals
andhashcode
– MadProgrammer