what is the internal working of System.idendityHashCode() and hashCode() method? - java

I read About System.identityHashCode(Object x). You can not override it because its static method but i can override Object's hashCode method. and also this is mentioned for System.identityHashCode(Object x) in javadoc as :
Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides
hashCode().The hash code for the null reference is zero.
but when i am running below code by swapping the object in println method i am getting same result.
public class SherlockGCD {
public int hashCode()
{
return super.hashCode();
}
public static void main(String[] args) {
SherlockGCD sher= new SherlockGCD();
SherlockGCD sher1= new SherlockGCD();
System.out.println(System.identityHashCode(sher));
System.out.println(sher1.hashCode());
}
}
Output is :
31866429
16795905
but if you swap the object as below then also same output
System.out.println(System.identityHashCode(sher1));
System.out.println(sher.hashCode());
Output is :
31866429
16795905
so why output is not reversing as i am changing the object in println method??

but when i am running below code by swapping the object in println method i am getting same result.
You shouldn't compare the results of a hashCode in one run with the results in a different run. For example, what you may have observed is that identity hash codes are allocated lazily - so whichever object you request the hash code for first gets 31866429 and the next gets 16795905 - on your particular system.
If you reverse the order within a single run you should see consistent results:
System.out.println(System.identityHashCode(sher));
System.out.println(sher1.hashCode());
System.out.println(System.identityHashCode(sher1));
System.out.println(sher.hashCode());
Here lines 1 and 4 of the output should have the same value, and lines 2 and 3 should have the same value.

It's unclear what you are trying to do. A given object reference has a given hashCode. This will be returned for both identityHashCode and a non-overridden hashCode. You however have two different object references. Therefore these will have different hashCodes if Object.hashCode is not overriden.
That you are seeing the same hashCodes between runs is chance. If you do this for long enough, and across enough JVM reboots that won't be the case.
The fact that you do see the same hashCodes in the same order is because the hashCodes are being allocated to the object reference only when you first call hashCode, not when the object is created. Therefore the first call to hashCode gets the first code in both runs, regardless of which object it is.
Try
// both lines output the same hashCode for sher
System.out.println(System.identityHashCode(sher));
System.out.println(sher.hashCode());
and
// both lines output the same hashCode for sher1
System.out.println(System.identityHashCode(sher1));
System.out.println(sher1.hashCode());
If you put all 4 lines next to each other you will see two identical lines, and then two more identical lines different to the first pair.
If you now want to return a different hashCode for hashCode() and identityHashCode then add a field and return a hashCode inside your override:
public class SherlockGCD {
private int id;
public SherlockGD(int id) { this.id = id; }
public int hashCode()
{
return id;
}
...

Related

Uses of hashcode in Java apart from hashing collections [duplicate]

In Java, obj.hashCode() returns some value. What is the use of this hash code in programming?
hashCode() is used for bucketing in Hash implementations like HashMap, HashTable, HashSet, etc.
The value received from hashCode() is used as the bucket number for storing elements of the set/map. This bucket number is the address of the element inside the set/map.
When you do contains() it will take the hash code of the element, then look for the bucket where hash code points to. If more than 1 element is found in the same bucket (multiple objects can have the same hash code), then it uses the equals() method to evaluate if the objects are equal, and then decide if contains() is true or false, or decide if element could be added in the set or not.
From the Javadoc:
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.
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 hashtables.
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.)
hashCode() is a function that takes an object and outputs a numeric value. The hashcode for an object is always the same if the object doesn't change.
Functions like HashMap, HashTable, HashSet, etc. that need to store objects will use a hashCode modulo the size of their internal array to choose in what "memory position" (i.e. array position) to store the object.
There are some cases where collisions may occur (two objects end up with the same hashcode), and that, of course, needs to be solved carefully.
The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal.
By definition, if two objects are equal, their hash code must also be equal. If you override the equals() method, you change the way two objects are equated and Object's implementation of hashCode() is no longer valid. Therefore, if you override the equals() method, you must also override the hashCode() method as well.
This answer is from the java SE 8 official tutorial documentation
A hashcode is a number generated from any object.
This is what allows objects to be stored/retrieved quickly in a Hashtable.
Imagine the following simple example:
On the table in front of you. you have nine boxes, each marked with a number 1 to 9. You also have a pile of wildly different objects to store in these boxes, but once they are in there you need to be able to find them as quickly as possible.
What you need is a way of instantly deciding which box you have put each object in. It works like an index. you decide to find the cabbage so you look up which box the cabbage is in, then go straight to that box to get it.
Now imagine that you don't want to bother with the index, you want to be able to find out immediately from the object which box it lives in.
In the example, let's use a really simple way of doing this - the number of letters in the name of the object. So the cabbage goes in box 7, the pea goes in box 3, the rocket in box 6, the banjo in box 5 and so on.
What about the rhinoceros, though? It has 10 characters, so we'll change our algorithm a little and "wrap around" so that 10-letter objects go in box 1, 11 letters in box 2 and so on. That should cover any object.
Sometimes a box will have more than one object in it, but if you are looking for a rocket, it's still much quicker to compare a peanut and a rocket, than to check a whole pile of cabbages, peas, banjos, and rhinoceroses.
That's a hash code. A way of getting a number from an object so it can be stored in a Hashtable. In Java, a hash code can be any integer, and each object type is responsible for generating its own. Lookup the "hashCode" method of Object.
Source - here
Although hashcode does nothing with your business logic, we have to take care of it in most cases. Because when your object is put into a hash based container(HashSet, HashMap...), the container puts/gets the element's hashcode.
hashCode() is a unique code which is generated by the JVM for every object creation.
We use hashCode() to perform some operation on hashing related algorithm like Hashtable, Hashmap etc..
The advantages of hashCode() make searching operation easy because when we search for an object that has unique code, it helps to find out that object.
But we can't say hashCode() is the address of an object. It is a unique code generated by JVM for every object.
That is why nowadays hashing algorithm is the most popular search algorithm.
One of the uses of hashCode() is building a Catching mechanism.
Look at this example:
class Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
if (x != point.x) return false;
return y == point.y;
}
#Override
public int hashCode()
{
int result = x;
result = 31 * result + y;
return result;
}
class Line
{
public Point start, end;
public Line(Point start, Point end)
{
this.start = start;
this.end = end;
}
#Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Line line = (Line) o;
if (!start.equals(line.start)) return false;
return end.equals(line.end);
}
#Override
public int hashCode()
{
int result = start.hashCode();
result = 31 * result + end.hashCode();
return result;
}
}
class LineToPointAdapter implements Iterable<Point>
{
private static int count = 0;
private static Map<Integer, List<Point>> cache = new HashMap<>();
private int hash;
public LineToPointAdapter(Line line)
{
hash = line.hashCode();
if (cache.get(hash) != null) return; // we already have it
System.out.println(
String.format("%d: Generating points for line [%d,%d]-[%d,%d] (no caching)",
++count, line.start.x, line.start.y, line.end.x, line.end.y));
}

Could not understand the output

In the below code different three outputs are coming depending upon the hashcode value generated for the object after running multiple times
Output1
collection.A#1
0
collection.A#0
0
true
Output2
collection.A#1
0
collection.A#0
1
true
Output3
collection.A#1
1
collection.A#1
1
true
I am not able to understand the three different outputs that are coming ,
For e.g Output3 why two objects are added if the hashcode is same of them and equals returns true
Simliarly I am not able to understand the Output1 & 2
public class A {
#Override
public int hashCode() {
long l=Math.round(Math.random());
return (int)l;
}
#Override
public boolean equals(Object arg0) {
return true;
}
public static void main(String args[]){
Set<A> h=new HashSet<A>();
for(int i=0;i<100;i++)
h.add(new A());
for (A a : h) {
System.out.println(a);
System.out.println(a.hashCode());
}
System.out.println(h.contains(new A()));
}
}
Basically, your code breaks the contract of hashCode().
One of the rules to implement hashCode is that this must always be true:
obj.hashCode() == obj.hashCode()
But in your case, this isn't. Every time hashCode is called, the result can be different from that of the previous call. This is because Math.random() returns a different value each time.
How come only two objects are added to the set?
Because only objects with different hash codes can be added to a HashSet. If an object with a hash code of 1 is added, another object with hash code of 1 cannot be added.
And since your hashCode method can only return two different integers - 1 and 0, at most 2 objects can be added.
In output 3, why do I see two objects of the same hash code in the set?
collection.A#1
1
collection.A#1
1
true
That is because your hashCode method may return different values every time you call it. Maybe when the two objects are added to the set, their hashCode method return different values. But by the time you call it, they change to the same value.
Anything can happen, ya know!
P.S. I hope this is not production code...
For e.g Output3 why two objects are added if the hashcode is same
Since the hashcode can be different each time you check it the strangeness of the results are to be expected.
If all 100 objects return the same hashcode (pairwise) when they are inserted then the set will contain only one object. The probability of this is 0.5^99 or almost 0.
When you print the result, you generate new hashcodes. The value you print is independent of the values used in the comparisons during insertion.
Try remembering the generated hashcode value in a field and have each object return the same value each time and the result will be the same every time.
Because your Math.round(Math.random()); always return 0 or 1. If you need larger range of random values, It should be like Math.round(Math.random()*10000);
You have to override toString() method as well in the Class A.
Add following method to Class A, or can modify it as your own.
#Override
public String toString() {
return "Class A";
}
Also change your hashCode() method as follows and try.
#Override
public int hashCode() {
long l=Math.round(Math.random()*10000);
return (int)l;
}
bcoz of Math.random()
The Math.random() returns a pseudorandom double greater than or equal to 0.0 and less than 1.0

Understanding HashSet

Well here is my question, Can "HashSet Objects" have elements duplicated??
If I read the Set Interface definition, I see:
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.
And now we are going to write a simple example:
Define class A:
public class A {
#Override
public boolean equals(Object obj) {
return true;
}
}
Now execute this code;
Set<A> set = new HashSet<A>();
set.add(new A());
set.add(new A());
System.out.println(set.toString());
And this is the result:
[com.maths.graphs.A#b9e9a3, com.maths.graphs.A#18806f7]
Why a class what implements Set Interface like HashSet contains elements duplicated?
Thanks!!
You have broken the equals-hashcode contract.
If you override the equals method you must also override the hashCode() method such that:
Two objects which are equal give the same hash, and preferably unequal
objects are highly likely to give different hashcodes
This is important because many objects (unsurprisingly including the HashSet) use the hashcode as a quick, efficient early step to eliminate unequal objects. This is what has happened here since the hashcodes of the different As will be different as they are still using the implementation of .hashCode() provided within object.
If you were to create the class A as follows it would not allow more than 1 A in the set
public class A {
#Override
public boolean equals(Object obj) {
return true;
}
#Override
public int hashCode() {
int hash = 1; //any number since in this case all objects of class A are equal to everything
return hash;
}
}
From the javadoc
public int hashCode()
Returns a hash code value for the object. This method is supported for
the benefit of hash tables such as those provided by HashMap.
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.
Most IDEs will object if you do not include an overriding HashCode method when overiding the equals method and can generate a hashCode method for you.
Notes
Strictly speaking my hashCode() method doesn't completely satisfy the contract. Since A#equals(Object obj) equals anything including objects which are not of type A it is impossible to fully satisfy the contract. Ideally the equals method would be changed to the following as well to cover all bases
#Override
public boolean equals(Object obj) {
if (obj instanceof A){
return true;
}else{
return false;
}
}
Here the HashSet does not have duplicates, as the two add methods add new objects in the HashSet and these are different Objects. The reason that the hash codes for the two elements of the set are different for this reason. Try changing the code to:
Set<A> set = new HashSet<A>();
A a = new A();
set.add(a);
set.add(a);
System.out.println(set.toString());
and you will see that there is only one value in the set.
Or just add the following in you code and check
#Override
public int hashCode() {
return 31;
}
You have violated the hashCode() method contract i.e for same key it should return same hashcode() every time

default implementation of hashcode returns different values for objects constructed the same way

Here I am writing one sample code:
public class Test {
private int i;
private int j;
public Test() {
// TODO Auto-generated constructor stub
}
public Test(int i, int j)
{
this.i=i;
this.j=j;
}
}
now I am creating two objects as bellow:
Test t1= new Test(4,5);
Test t2 = new Test(4,5);
But when i am printing t1.hashcode() and t2.hashcode() they are giving different values.
But as per java's general contact they should return same value.
In fact, when i am doing same thing with String or Integer they are returning same hashcode(). Can anyone please explain why hashcode is different for t1 and t2 object?
But as per java's general contact they should return same value.
Java's equals-hashCode contract requires that if two objects are equal by Object.equals, they must have the same hashcode from Object.hashCode. But the default implementation of Object.equals is reference equality, and therefore two instances are the same if and only if they are the same instance.
Therefore, in particular, your two instances t1 and t2 are in fact not equal because you have not overridden Object.equals. They are not equal as references, and therefore not equal per Object.equals, and therefore it is acceptable for hashCode to possibly return different values. In fact, the contract explicitly says the following:
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.
Thus, we do not have a violation of the equals-hashCode contract here.
So, for your objects, if you want different instances to be equal per a logical definition of equality, you need to override Object.equals:
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
if (this == obj) {
return true;
}
if (!(obj instanceof Test)) {
return false;
}
Test other = (Test)obj;
return this.i == other.i && this.j == other.j;
}
And the equals-hashCode contract requires that you override Object.hashCode too or you'll run into some nasty bugs:
#Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.i;
hash = 31 * hash + this.j;
return hash;
}
What does the contract say:
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.
Let's see if we have satisfied this requirement here. If x and y are instances of Test and satisfy x.equals(y) is true, we have that x.i == y.i and x.j == y.j. Then, clearly, if we invoke x.hashCode() and y.hashCode() we have the invariant that at each line of execution in Test.hashCode we will have hash holding the same value. Clearly this is true on the first line since hash will be 17 in both cases. It will hold on the second line since this.i will return the same value whether this == x or this == y because x.i equals y.i. Finally, on the penultimate line, we will still have hash being equal across both invocations because x.j equals y.j is true as well.
Note that there is one last piece of the contract that we haven't discussed yet. This is the requirement that hashCode return a consistent value during a single execution of a Java application:
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.
The necessity of this is obvious. If you change the return value from hashCode during a single execution of the same application, you could lose your objects in hashtable-like data structures that use hashCode to keep track of objects. In particular, this is why mutating objects that are keys in hashtable-like data structures is pure evil; don't do it. I would go so far as to argue that they should be immutable objects.
In fact, when i am doing same thing with String or Integer they are returning same hashcode().
They've both overridden Object.equals and Object.hashCode.
You have not overridden the equals method in your class so the default one will be used that belongs to Object class.
Object class methods simply checks for the references whether they are referring to the same object or not.
Test t1 = new Test(4,5);
Test t2 = new Test(4,5);
are two different objects, if you don't override the equals method here, they will be equal if and only if you do
Test t2 = t1;
As you are creating two different objects here, hashcode which are NOT equal because they don't refer to the same object, hashcodes must be differnt
Remember
If two objects are equal, then their hashcode MUST be equal
But if hashcodes are equal, then its not necessary that objects should be equal
This is because of the default implementation of equals and hashCode in Java.
The JVM has no way of knowing how you decide that two objects are the same. What it does is use memory references. So, by default, the equals and hashCode methods compare memory references; i.e. two different objects are never .equals.
If you want to override this behaviour (and it is recommended you do so if you wish to use Collections for example) then all you need to do is implement your own equals and hashCode methods.
The problem is that t1 and t2 are not the same object they are different object. All objects created with new are different objects. And the default hashCode() implementation usually returns different hash codes for different objects. See Object.hashCode API.

Why should I override hashCode() when I override equals() method?

Ok, I have heard from many places and sources that whenever I override the equals() method, I need to override the hashCode() method as well. But consider the following piece of code
package test;
public class MyCustomObject {
int intVal1;
int intVal2;
public MyCustomObject(int val1, int val2){
intVal1 = val1;
intVal2 = val2;
}
public boolean equals(Object obj){
return (((MyCustomObject)obj).intVal1 == this.intVal1) &&
(((MyCustomObject)obj).intVal2 == this.intVal2);
}
public static void main(String a[]){
MyCustomObject m1 = new MyCustomObject(3,5);
MyCustomObject m2 = new MyCustomObject(3,5);
MyCustomObject m3 = new MyCustomObject(4,5);
System.out.println(m1.equals(m2));
System.out.println(m1.equals(m3));
}
}
Here the output is true, false exactly the way I want it to be and I dont care of overriding the hashCode() method at all. This means that hashCode() overriding is an option rather being a mandatory one as everyone says.
I want a second confirmation.
It works for you because your code does not use any functionality (HashMap, HashTable) which needs the hashCode() API.
However, you don't know whether your class (presumably not written as a one-off) will be later called in a code that does indeed use its objects as hash key, in which case things will be affected.
As per the documentation for Object class:
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.
Because HashMap/Hashtable will lookup object by hashCode() first.
If they are not the same, hashmap will assert object are not the same and return not exists in the map.
The reason why you need to #Override neither or both, is because of the way they interrelate with the rest of the API.
You'll find that if you put m1 into a HashSet<MyCustomObject>, then it doesn't contains(m2). This is inconsistent behavior and can cause a lot of bugs and chaos.
The Java library has tons of functionalities. In order to make them work for you, you need to play by the rules, and making sure that equals and hashCode are consistent is one of the most important ones.
Most of the other comments already gave you the answer: you need to do it because there are collections (ie: HashSet, HashMap) that uses hashCode as an optimization to "index" object instances, an those optimizations expects that if: a.equals(b) ==> a.hashCode() == b.hashCode() (NOTE that the inverse doesn't hold).
But as an additional information you can do this exercise:
class Box {
private String value;
/* some boring setters and getters for value */
public int hashCode() { return value.hashCode(); }
public boolean equals(Object obj) {
if (obj != null && getClass().equals(obj.getClass()) {
return ((Box) obj).value.equals(value);
} else { return false; }
}
}
The do this:
Set<Box> s = new HashSet<Box>();
Box b = new Box();
b.setValue("hello");
s.add(b);
s.contains(b); // TRUE
b.setValue("other");
s.contains(b); // FALSE
s.iterator().next() == b // TRUE!!! b is in s but contains(b) returns false
What you learn from this example is that implementing equals or hashCode with properties that can be changed (mutable) is a really bad idea.
It is primarily important when searching for an object using its hashCode() value in a collection (i.e. HashMap, HashSet, etc.). Each object returns a different hashCode() value therefore you must override this method to consistently generate a hashCode value based on the state of the object to help the Collections algorithm locate values on the hash table.

Categories