You dug up an old post (from 2007), but ok...
That is because of how collection classes such as HashMap and HashSet work. Those collection classes depend on the fact that the objects that you put into them obey the hash code contract. If your objects do not obey the contract, then what happens if you try to store them in a HashMap or HashSet is undefined - in other words, strange, unpredictable things can happen.
If you want to know all the details, you'll have to study how for example HashMap works internally. You don't need to know the exact details for the
SCJP exam. Here is some background information.
In for example a HashSet, the values contained in the set are stored in a set of "buckets". Each of those buckets has a number to identify it. When you put a value into the HashSet, it gets stored into the bucket which is identified by the hash code of the object that you put into it. For example, if I have an object for which hashCode() returns 25 then it gets stored into bucket 25 in the HashSet.
If you later want to check if the HashSet contains a certain object, by calling contains(someObject) on the HashSet, the following happens: The HashSet gets the hash code for someObject. It then looks into the bucket that corresponds with the hash code. If there is nothing in the bucket, then it's done, the HashSet doesn't contain someObject, so it returns false. If there are one or more objects in the bucket, the HashSet has to go through all of them and compare them with someObject, by calling equals() on each pair of someObject and object in the bucket. If equals() returns true for a pair, contains() returns true, otherwise it returns false.
The reason why it works like this, is because it is efficient, especially compared to for example a List. If all the objects in the HashSet would be stored into one big list, it would mean that if you want to check if an object is in the set, you would have to compare the input with all the objects in the list. With the scheme with buckets, you only have to compare the input with the content of one bucket - and any bucket normally contains only a small fraction of all the elements in the set.
It's legal to implement your hashCode() method to always return a fixed value, for example like this:
This hashCode() method conforms to the hash code contract, but is bad, because it kills the efficiency advantage of the mechanism with the buckets. All objects would be stored in bucket 0, and when you check the set, it always has to check all the elements in bucket 0 - the whole content of the set.
If you would write a hashCode() method that breaks the contract, the HashSet will look into the wrong bucket, which means that contains(someObject) may return false, even though the object you're looking for really is in the set (in a different bucket).
Note also that
you should never put mutable objects in a HashSet or HashMap. If you put such an object in a HashSet and then change the state of the object so that the hash code changes, the object will be in the wrong bucket in the HashSet.
See also:
http://en.wikipedia.org/wiki/Hash_table