CorayThan
CorayThan

Reputation: 17825

Performance warning in Guava ImmutableMap

In the javadocs for Guava's ImmutableMap it says:

Performance notes: unlike HashMap, ImmutableMap is not optimized for element types that have slow Object.equals(java.lang.Object) or Object.hashCode() implementations. You can get better performance by having your element type cache its own hash codes, and by making use of the cached values to short-circuit a slow equals algorithm.

So my first question is how do I know if my element has a slow .equals or .hashCode implementation? In my specific instance, I'm using a java Enum as my key, so that has an efficient default implementation of .equals and .hashCode, right? (I assume the implementation of those for the values is irrelevant so long as you aren't accessing the map using the values' values.)

My second question is what does "having your element type cache its own hash codes" even mean! Googling around I couldn't seem to find an example of how you would do that. I assume maybe that means you end up with hashcodes within hashcodes? So I get into the hashcode bucket, and then the .equals methods uses a second set of hashcodes within that?

Upvotes: 2

Views: 2036

Answers (3)

Jan Mares
Jan Mares

Reputation: 805

I know this is very old question, but for those who got here like me - you really should be using an EnumpMap, if your key is an enum.

Upvotes: 0

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

If your key is an Enum then this is not an issue for you.

What they are talking about with caching hash codes would be something like:

private volatile int hashCode = -1;

@Override
public int hashCode() {
  if ( hashCode == -1 ) {
    hashCode = longCalculation();
  }
  return hashCode;
}

Upvotes: 2

assylias
assylias

Reputation: 328618

I'm using a java Enum as my key, so that has an efficient default implementation of .equals and .hashCode, right?

Neither equals or hashcode are overriden so it could hardly be much faster (i.e. equals returns this == other).

My second question is what does "having your element type cache its own hash codes" even mean!

You could have something like the code below, to avoid multiple calculation - if you do that, you need to make sure that:

  • the hashcode is invariant (i.e. can't change throughout the life of an instance)
  • your hashcode method is thread safe (which can be done with the use of a local variable for example or more simply by making hash volatile).
class MyClass {
    private int hash;

    public int hashcode() {
        int hash = this.hash;
        if (hash == 0) {
            hash = calculateIt();
            this.hash = hash;
        }
        return hash;
    }
}

Upvotes: 4

Related Questions