Reputation: 730
Till today I had a belief that Two objects having the same hashcode means both of them have same memory location. But below piece of code tells altogether a different story :
Student Entity: public class Student implements Comparable {
int id;
int marks;
String Subject;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getMarks() {
return marks;
}
public void setMarks(int marks) {
this.marks = marks;
}
public String getSubjects() {
return Subject;
}
public void setSubject(String subject) {
Subject = subject;
}
public Student() {
}
public Student(int id, String subject, int marks) {
super();
this.id = id;
this.marks = marks;
Subject = subject;
}
@Override
public int compareTo(Student o) {
if (this.getId()>(o.getId()))
return 1;
if (this.getId()<(o.getId()))
return -1;
return 1;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Subject == null) ? 0 : Subject.hashCode());
result = prime * result + id;
result = prime * result + marks;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (Subject == null) {
if (other.Subject != null)
return false;
} else if (!Subject.equals(other.Subject))
return false;
if (id != other.id)
return false;
if (marks != other.marks)
return false;
return true;
}
}
Entering Duplicates in Hashmap to check whether overriding equals & hashcode() works :
public class TestHashSet3 {
static Student s1;
static Student s2;
static Student s3;
public static void main(String[] args) {
setStudent();
testSet();
testMap();
}
static void testMap() {
Map<Student, String> empMap = new HashMap<>();
empMap.put(s1, "Arun");
empMap.put(s2, "Shivam");
empMap.put(s3, "Varun");
System.out.println("HashMap executed = ");
for (Map.Entry<Student, String> obj : empMap.entrySet()) {
System.out.println(obj + " ");
}
}
static void testSet() {
Set<Student> set = new HashSet<>();
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println("HashSet executed = ");
for (Student student : set) {
System.out.println(student + " ");
}
}
static void setStudent() {
s1 = new Student(124, "Maths", 50);
s2 = new Student(124, "Maths", 50);
s3 = new Student(124, "Maths", 50);
}
}
In last screenshot, we can see that this ==obj turns out to be false. But why ?
Upvotes: 1
Views: 1327
Reputation: 5326
hashcode is an int value which is returned by hascode() method.
Object.java defines hascode() and every java class is a sub class of Object.java, hence each class inherits it.
It is upto the developer of a particular class if he/she wishes to override it. Developer of a class may choose (although a bad practice) to retrun same constant int value for all objects of a class.
Usually hascode is dependent on value of one or more properties of the object. Even though developer may try best to return unique hashcode but still (hashcode collision) two different objects may end up eith same hascode.
At One memory location at a time can only be assigned to only one Object.
Hashcode of two different objects (residing at two different address in memeory) may be same or may be different
Also a related concept : contract of equals and hascode method. It says if two objects have true returned by invoking equals then both object must have same hashcode. Note that this is a contract defined but it is upto the developer developing the class and writing the hashcode method to adhere to the contract. A bad implementation may result in different hascodes being returned by two objects returning true for equals method.
Upvotes: 1
Reputation: 372982
You have correctly just identified that two different objects - that is, two objects not at the same memory address - can indeed have the same hash code. The rules is that if two objects are equal by the .equals()
method, then they should produce the same hash code. Aside from this and a general idea that “different objects should try to have different hash codes,” there’s no requirement that objects at different locations should hash differently.
This is a good thing, though. For example, two different String
objects that each have the same character sequence should intuitively have the same hash code so that HashMap<String, T>
can properly look up strings. That way, providing a different String
object than the one used as a key, but which has the same logical value, will work correctly; all String
s with the same character sequence hash to the same spot.
Upvotes: 1
Reputation: 14189
Well, it's not exactly true that hashCode()
always returns the memory address. In your specific case, you are overwriting the function to basically return the hashCode of the Subject
reference.
Your evaluate shows the following output:
stringops.Student@955a0720
which might be a bit confusing as this is actually NOT the bare memory address but a call to the toString()
method of your object.
Have a look at how Java implements toString
:
getClass().getName() + '@' + Integer.toHexString(hashCode())
So, in fact, those two objects have different memory locations, but because you overwrite hashCode()
you won't get to see them. Also, there is no way to overwrite how Java selects the memory address of an object (except some hacks maybe), but nevertheless, two objects can't have the same address.
Please include more text instead of screenshots next time to increase searchability of your question for others.
Upvotes: 2