HashSet in java confused me a lot, when using contains() will it look up hashcode() and equals() result ?
But in this case, it doesn’t behave normal.
Sometime it’s problematic if you put this kind of code in large project.
Problem is why last statement print FALSE ?what contains() do under the hood ?
class R
{
int count;
public R(int count)
{
this.count = count;
}
public String toString()
{
return "R(count attribution:" + count + ")";
}
public boolean equals(Object obj)
{
if (obj instanceof R)
{
R r = (R)obj;
if (r.count == this.count)
{
return true;
}
}
return false;
}
public int hashCode()
{
return this.count;
}
}
public class TestHashSet2
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add(new R(5));
hs.add(new R(-3));
hs.add(new R(9));
hs.add(new R(-2));
System.out.println(hs);
//change first element
Iterator it = hs.iterator();
R first = (R)it.next();
first.count = -3;
System.out.println(hs);
//remove
hs.remove(new R(-3));
System.out.println(hs);
R r1 = new R(-3);
System.out.println(r1.hashCode());
Iterator i = hs.iterator();
R r2 = (R)i.next();
System.out.println(r2.hashCode()); //same hashcode -3
System.out.println(r1.equals(r2)); //equals true
System.out.println("hs contains object which count=-3 ?" + hs.contains(new R(-3))); //false
}
}
The
HashSetstores the values in buckets, the bucket index is calculated when you add the element to the hash set. The idea behind it: now the set can read an objects hashcode and calculate the bucket in a single step. In other words:contains()is a O(1) operation.Imagine a trivial hash set:
with a hash function to calculate buckets like:
Now have look at what you done in your example: you’ve removed the object in bucket 2 (changes the function) and changed the hashcode of the object in bucket 1.
The new function looks like:
f(-3)will return null (contains()returns false) and your actual object with hashcode -3 is stored where an object with hashcode 5 should be.