8

I have an immutable object, for example a node in the Cartesian space. The class is immutable, so I cache the hashCode for very fast hashing.

private final int hashCode;

private final double x, y, z;

public Node(final double x, final double y, final double z)
{
    this.x = x;
    this.y = y;
    this.z = z;
    this.hashCode = Objects.hashCode(this.x, this.y, this.z);
}

@Override
public boolean equals(final Object obj)
{
    if (this == obj) { return true; }
    if (obj == null) { return false; }
    if (!(obj instanceof Node)) { return false; }
    final Node other = (Node) obj;
    return Objects.equal(this.x, other.x) && Objects.equal(this.y, other.y) && Objects.equal(this.z, other.z);
}

@Override
public int hashCode()
{
    return this.hashCode;
}

Since the hashCode is unique and dependent on all fields of the class AND the class is Immutable, would it be correct to only check Node equality based on the hashCode?

@Override
public boolean equals(final Object obj)
{
    if (this == obj) { return true; }
    if (obj == null) { return false; }
    if (!(obj instanceof Node)) { return false; }
    final Node other = (Node) obj;
    return this.hashCode == other.hashCode;
}

This passes all Unit Tests I have written about the properties of equals() and hashCode() and their interaction, but perhaps there is something I am missing?

Note: Objects.hashCode() and Objects.equal() are Guava classes helpful for the respective methods.

7
  • 12
    Repeat after me: Hashcodes are not unique. Commented Apr 18, 2012 at 0:25
  • 4
    BTW, your second if is a subset of the third. Commented Apr 18, 2012 at 0:26
  • 1
    For reference, as also mentioned here: stackoverflow.com/a/7417858/713659 , you can check for hashCode first before going into more expensive equality checks, but you cannot skip other checks. Commented Apr 18, 2012 at 0:36
  • 1
    FYI, there's no need to use Objects.equal in the equals implementation, since you're comparing primitives. == will be faster and simpler. Commented Apr 18, 2012 at 0:50
  • 1
    In this case, it's basically equivalent to Objects.equal. Commented Apr 18, 2012 at 1:49

2 Answers 2

17

Nope; that won't work.

You have 232 possible hashcodes and 2192 possible values.

Sign up to request clarification or add additional context in comments.

Comments

2

No, but..

I guess you could check the hashcode to see whether objects are not equal and gain some performance there:

public boolean equals(final Object obj) {
   if (this == obj) { return true; }
   if (!(obj instanceof Node)) { return false; }
   final Node other = (Node) obj;

   if (this.hashCode != other.hashCode) {
      return false; // If hashcodes differ, we're sure the objects are not equal
   }
   // remainder of the actual equals implementation
}

Of course this will only improve performance in case most of your comparisons yield false. In case of equal objects, this will bring a performance penalty. In your example (comparing just three values), I wouldn't recommend this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.