CodeGym /Courses /JAVA 25 SELF /The Objects class: equals, hashCode, hash methods

The Objects class: equals, hashCode, hash methods

JAVA 25 SELF
Level 29 , Lesson 1
Available

1. Getting started with the Objects class

Let’s get to it! If you’re tired of manually checking values for null and writing hash calculations for every field, the utility class java.util.Objects will help. Its job is to make working with objects simpler, more concise, and safer.

It really is a “Swiss Army knife”: the class can safely compare objects for equality (without risking a NullPointerException), conveniently compute hash codes, compare via a comparator, and validate arguments for null.

Objects.equals: null-safe comparison

If you just write a.equals(b) and a happens to be null, you’ll get a NullPointerException. Manual checks are verbose. Objects.equals(a, b) does it all for you:

  • If both are null — returns true.
  • If exactly one is null — returns false.
  • If both are not null — calls the regular equals.
import java.util.Objects;

String a = null;
String b = "Java";
System.out.println(Objects.equals(a, b)); // false

String c = null;
System.out.println(Objects.equals(a, c)); // true

String d = "Java";
String e = "Java";
System.out.println(Objects.equals(d, e)); // true

Why is this convenient? The code is shorter, cleaner, and protected against accidental NPEs.

2. Objects.hash and hashCode: concise hash computation

When overriding hashCode alongside equals, it’s easy to make mistakes, especially when there are many fields. Manual code often looks verbose and brittle:

@Override
public int hashCode() {
    int result = 17;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + age;
    return result;
}

The Objects.hash method fixes this—short, safe, and null-friendly:

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    // ... constructor, getters, etc.

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

Important note: Objects.hash uses varargs and allocates an array—in rare high-throughput hotspots a hand-written hashCode may be faster. For most applications the difference is negligible.

3. Objects.compare: delegate comparison to a comparator

Sometimes you need to compare two objects using a prebuilt Comparator. Instead of calling comparator.compare(a, b) directly, you can use:

int result = Objects.compare(a, b, comparator);

This method:

  • Returns 0 if the objects are equal.
  • Treats null as “less than” any non-null object.
  • In all other cases delegates the logic to the provided comparator.
import java.util.Comparator;
import java.util.Objects;

class Person {
    private String name;
    Person(String name) { 
        this.name = name; 
    }
    public String getName() { 
        return name; 
    }
}

public class Main {
    public static void main(String[] args) {
        Person a = new Person("Anna");
        Person b = new Person("Boris");
        Comparator<Person> byName = Comparator.comparing(Person::getName);

        System.out.println(Objects.compare(a, b, byName)); // <0, because "Anna" < "Boris"
        System.out.println(Objects.compare(a, null, byName)); // >0, because a != null
        System.out.println(Objects.compare(null, b, byName)); // <0, because null < b
        System.out.println(Objects.compare(null, null, byName)); // 0
    }
}

4. Objects.requireNonNull: insurance against “invisible” errors

If a method must accept only non-null values, check this immediately. Objects.requireNonNull will throw a NullPointerException with your message:

public void setName(String name) {
    this.name = Objects.requireNonNull(name, "Name must not be null");
}

5. Example: correct implementation of equals, hashCode and compareTo with Objects

import java.util.Objects;

public class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = Objects.requireNonNull(name, "Name must not be null");
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true; // Reference equality
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        // Null-safe comparison
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age); // Concise and safe
    }

    @Override
    public int compareTo(Person other) {
        // First compare by name, then by age
        int cmp = name.compareTo(other.name);
        if (cmp != 0) return cmp;
        return Integer.compare(age, other.age);
    }
}

Now you can store objects in a HashSet, use them as keys in a HashMap, compare them for equality, and sort lists (for example, via Collections.sort).

6. Practical use: less code and fewer bugs

Example: a user list in an application

Thanks to a correct equals/hashCode pair, searching in collections works predictably:

import java.util.ArrayList;
import java.util.List;

List<Person> users = new ArrayList<>();
users.add(new Person("Anna", 25));
users.add(new Person("Boris", 30));

Person search = new Person("Anna", 25);
System.out.println(users.contains(search)); // true

Example: working with nullable fields

If a class has fields that can be null (for example, middle name), use Objects.equals and Objects.hash:

import java.util.Objects;

public class User {
    private String firstName;
    private String middleName; // May be null
    private String lastName;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(firstName, user.firstName)
            && Objects.equals(middleName, user.middleName)
            && Objects.equals(lastName, user.lastName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstName, middleName, lastName);
    }
}

7. Table: key methods of the Objects class

Method Purpose Usage example
Objects.equals(a, b)
Null-safe comparison of two objects
Objects.equals(a, b)
Objects.hash(a, b, ...)
Concise hash-code computation over multiple fields
Objects.hash(name, age)
Objects.compare(a, b, comparator)
Comparator-based comparison, null-safe
Objects.compare(p1, p2, byNameComparator)
Objects.requireNonNull(obj[, msg])
Null check, throws NullPointerException
Objects.requireNonNull(name, "Name must not be null")
Objects.isNull(obj) / Objects.nonNull(obj)
Check for null/non-null (handy in the Stream API)
list.stream().filter(Objects::nonNull)

8. Common mistakes when using the Objects class

Mistake #1: forgot to use Objects.equals for nullable fields. If you compare fields directly via equals, you can hit a NullPointerException. Use Objects.equals(middleName, other.middleName).

Mistake #2: not all fields are accounted for in hashCode. Fields that participate in equals must also participate in hashCode, otherwise HashSet/HashMap behaviour becomes unpredictable.

Mistake #3: a bug in a hand-written hashCode. It’s not trivial to pick factors and handle null correctly. Objects.hash does it for you; use it unless you have strict performance requirements.

Mistake #4: not using Objects.requireNonNull where the class contract demands it. If a field must not be null, validate it in the constructor/setter—the error will surface immediately instead of “somewhere deep” in the call stack.

Mistake #5: using Objects.hash for arrays. For arrays use Arrays.hashCode, and for nested arrays use Arrays.deepHashCode; similarly, to compare contents use Arrays.equals/Arrays.deepEquals.

1
Task
JAVA 25 SELF, level 29, lesson 1
Locked
Creating a digital fingerprint for books in the catalog 📚
Creating a digital fingerprint for books in the catalog 📚
1
Task
JAVA 25 SELF, level 29, lesson 1
Locked
Sorting event participants by name 🧑‍🤝‍🧑
Sorting event participants by name 🧑‍🤝‍🧑
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION