3

I've just realised HashMap<K,V> checks k.hashCode() = key.hashCode() and k == key.

So, it's regardless whether k is "equivalent" to key, k must be == to key.

Is it possible to change this behaviour in order to use only hashCode() equivalence?

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • 1
    This question is not at all the same as the nominated dupe. That question speaks to why `equals()` should be consistent with `hashCode()`, but this one is about how to implement / use a `Map` such that keys having the same hash code are considered equivalent for the map's purposes. They're related, but closely so. – John Bollinger Jul 12 '16 at 14:23

3 Answers3

4

No hashCode does a grouping for you (put the elements into buckets) and in the bucket the equals is used for comparison.

Check the following link: How does a Java HashMap handle different objects with the same hash code?

Community
  • 1
  • 1
wake-0
  • 3,918
  • 5
  • 28
  • 45
2

So, it's regardless whether k is "equivalent" to key, k must be == to key.

No, that is incorrect, as @KevinWallis already observed. HashMap uses hashCode() to identify the correct hash bucket, and equals(), not ==, to compare keys that fall into the same bucket. Types that have a meaningful sense in which distinct instances are equivalent are supposed to describe that via their equals() methods, and standard library types such as String and Integer in fact do so. When the keys are of such a type, you do not have to use the same object to retrieve a value from a HashMap that you did to store it.

On the other hand, types that do not have a meaningful sense in which distinct instances are equivalent should not, and generally do not, override equals() (or hashCode()). The implementation inherited from Object yields the same result as the == operator, which makes it possible and sensible to use such objects as HashMap keys or to store them in HashSets, at least under some circumstances.

Is it possible to change this behaviour in order to use only hashCode() equivalence?

It is not possible to change the behavior of HashMap in this regard. If you were able to do so then the resulting map would not correctly fulfill the Map contract. You can, however, implement your own map-like class that behaves as you describe, or you can create a wrapper class to use as a substitute key type.

Example key class:

class HashEquivalenceKey<T> {
    private final T object;

    public HashEquivalenceKey(T object) {
        this.object = object;
    }

    public int hashCode() {
        return ((o == null) ? 0 : object.hashCode());
    }

    public boolean equals(Object o) {
        return ((o != null) && (this.hashCode() == o.hashCode()));
    }
}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

Is it possible to change this behaviour in order to use only hashCode() equivalence?

Yes, you can override equals to return true when the two compared objects have the same hashCode(). Whether or not it would make sense is another matter.

public class SomeKeyClass
{
    boolean equals (Object other)
    {
        if (!(other instanceof SomeKeyClass)) // you can skip this condition too, but it
                                              // makes sense to require the two objects to
                                              // be of the same class in order for them to
                                              // be equal
            return false;
        return hashCode () == other.hashCode ();
    }
}
Eran
  • 387,369
  • 54
  • 702
  • 768