Java equality answers need to distinguish object identity, logical equality and the hash code used by hash-based collections. Two objects can hold equivalent information without being the same object. A correct equals implementation and a matching hashCode contract let collections work with that logical meaning.

The example uses Java 21 records. Run it with assertions enabled, for example with java -ea after compiling the class. It demonstrates value keys, not the internal implementation details of every map.

How can two separate objects be equal?

import java.util.HashMap;
import java.util.Map;

class Example {
    record Code(String value) {}
    public static void main(String[] args) {
        Code first = new Code("A7");
        Code second = new Code("A7");
        assert first != second;
        assert first.equals(second);
        assert first.hashCode() == second.hashCode();
        Map<Code, String> labels = new HashMap<>();
        labels.put(first, "north");
        assert "north".equals(labels.get(second));
    }
}

The record's component value supplies logical equality here. The two constructions still create different objects. The map can find an entry through an equal key because equality and hashing agree.

Must different objects have different hash codes?

No. Unequal objects can have the same hash code. Equal objects must have equal hash codes under the contract. A collision is therefore possible and is not proof that equals is broken.

Also avoid treating a hash code as a permanent business identifier. It is an aid to particular operations, not a promise of uniqueness, secrecy or a stable cross-system identity.

What goes wrong with mutable key fields?

If fields used by equals and hashCode change while an object is used as a map key, later lookup may no longer behave as intended. The key was placed under assumptions that its logical identity would remain consistent.

The record in the example contains a String component and is convenient for this small immutable-value case. A record containing a mutable component would require further thought. The word record does not recursively freeze every reachable object.

What should an equals answer mention?

Explain the intended equivalence first. Then consider reflexivity, symmetry, transitivity, consistency under unchanged relevant information and comparison with null. Inheritance can make a careless equality design particularly difficult when a subclass adds new fields.

Do not generate equals based on a field merely because it is available. For example, a display label that can be edited may not be the intended identity of an entity. Value equality and persistent entity identity are design choices with different consequences.

How is reference comparison different?

For object references, == asks whether they refer to the same object. Equals can express logical equality when the class implements it that way. Some classes retain identity-based equality, so never claim every pair of objects with similar printed text is equal.

Strings can make identity examples misleading because literals and runtime constructions can have different sharing behavior. A simple value record is often clearer for discussing the contract without turning the whole answer into a string-pool puzzle.

Checks to include in a small test

  • Two equivalent values compare equal and have equal hashes.
  • A different value does not accidentally compare equal.
  • A collection lookup works through a separately created equal key.
  • The key's relevant state does not change during use.

For a follow-up, replace Code with a custom class and write the intended equality tests before implementing the methods. A useful answer explains the chosen identity and its constraints, rather than relying on an IDE-generated method as the entire explanation.

References and next practice

docs.oracle.com — java objects · docs.oracle.com — java maps

java question collection · Browse interview topics · Practise a question in Interview Challenge · How to Answer Technical Interview Questions Out Loud