liveBook · Manning

Objects.hash

As explained in 100 Java Mistakes and How to Avoid Them

Objects.hash is a Java library method that computes a hash code from a sequence of object values.

Objects.hash() is a convenient way to compute a hash code from object values, but it is not suitable for every equals() implementation. When equality treats two fields as interchangeable, Objects.hash(f1, f2) produces different results after the fields are swapped, violating the hashCode() contract. section 7.8

The unordered-fields trap

Suppose TwoFields considers (1, 2) equal to (2, 1). Objects.hash(1, 2) returns 994, while Objects.hash(2, 1) returns 1,024. Use a symmetric calculation such as f1 + f2, or normalize the fields during construction so generated equals() and hashCode() remain valid. section 7.8

Choose the implementation according to the equality rule:

  • Use Objects.hash() when the fields have ordinary order-sensitive equality. section 7.8
  • Do not use Objects.hash(f1, f2) when equals() treats f1 and f2 as interchangeable; use a symmetric hash instead. section 7.8
  • Prefer IDE-generated equals() and hashCode(), or normalize immutable objects on construction when that restores ordinary field equality. section 7.8 section 2.1.1
class TwoFields {
  int f1, f2;

  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    TwoFields twoFields = (TwoFields) o;
    return f1 == twoFields.f1 && f2 == twoFields.f2 ||
           f1 == twoFields.f2 && f2 == twoFields.f1;
  }
}

Inspect the unordered equality rule that makes a direct Objects.hash(f1, f2) implementation unsafe. section 7.8

public int hashCode() {
  return f1 + f2;
}

Compare a symmetric addition-based hash with the order-sensitive result from Objects.hash(). section 7.8

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains order sensitivity with numeric results and stops short of implementing every custom equality strategy.
Examples
Uses unordered integer fields, Objects.hash(1, 2) versus Objects.hash(2, 1), and addition as a symmetric alternative.
What it assumes
Assumes familiarity with equals() and hashCode(), while reinforcing their contract through a focused counterexample.
What you can do after
Evaluate/understand when Objects.hash() preserves the equals() and hashCode() contract, then select a safer alternative when necessary.
How it connects
Connects Objects.hash() to equals(), hashCode(), immutable objects, Java records, and set equality.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.