I'm studying java and facing a really weird problem, i think it's easier to explain this along with my code
So this is my class:
class Node
{
private int val;
public Node(int val)
{
this.val = val;
}
public int getVal()
{
return this.val;
}
public void setVal(int newVal)
{
this.val = newVal;
}
@Override
public int hashCode() {
return this.val;
}
@Override
public boolean equals(Object obj) {
System.out.println("Inside equal of " + this.val);
//i expect it will print out when i use set.contains()
if(this.hashCode() == ((Node)obj).hashCode())
{
return true;
}
return false;
}
}
And this is my Main block using HashSet that working with class Node
public class Main
{
public static void main(String[] args)
{
Set<Node> s = new HashSet<>();
Node n1 = new Node(1);
s.add(n1);
/*as i know, when we add a object to the set, we actually add a refference to the origin memory area (the one that n1 points to) to the set*/
if(s.contains(n1))
{
System.out.println("YES");
}
for(Node i : s)
{
i.setVal(5); //i expect n1 to change too and it does
}
for(Node i : s)
{
System.out.println(i.getVal());
}
System.out.println(n1.getVal()); //n1 changes
if(s.contains(n1))
{
System.out.println("Still here");
//This is where i don't understand why this does not print ?
}
System.out.println();
}
}
This is my cmd
D:\Desktop\draft\JavaDraft>java Main
YES
5
5
I don't understand why set does not realize n1 still be in it and why the code inside function "equals" of class Node is not triggered because as i know, HashSet uses "equals" to get uniqueness of all of it's element right? Thank you in advance.
That is because by modifying the value of the Node, you are also changing the hashcode (thanks to your hashcode override). This is generally not the case and should not be the case as you do not want the hashcode to be variable. It should be constant and unchanging.
The underlying code of HashSet uses a HashMap, and the internal methods that
contains()uses will use the hashcode of the object to determine a bucket to store your node in. Thus, when your hashcode is set to the value 1, and you calladd(), the node n1 is stored for example at bucket 1. When you changed the value to 5, the hashcode is now 5 and callings.contains(n1)will try to check for your node in bucket 5 which is empty (null).A correct way to proceed will be to delete your implemented hashcode override and let the default implementation do its job. See also:
Output:
Without Hashcode override
With Hashcode override