Implementing Object Comparison in Java

Primitive data types in Java can be directly compared using relational operators.

int valueA = 5, valueB = 10;
System.out.println(valueA > valueB); // false
System.out.println(valueA == valueB); // false
System.out.println(valueA < valueB); // true

char charA = 'm', charB = 'z';
// Compares underlying Unicode values
System.out.println(charA > charB); // false
System.out.println(charA == charB); // false
System.out.println(charA < charB); // true

For reference types, direct comparison is not meaningful. This article explores three approaches for comparing objects.

We'll use a GameTile class as an example, representing a tile with a value and a color.

class GameTile {
    int value;
    String color;

    public GameTile(int value, String color) {
        this.value = value;
        this.color = color;
    }
}

Overriding Object.equals()

All user-defined classes inherit from Object, which provides a default equals() method.

// Default implementation in Object class
public boolean equals(Object obj) {
    return (this == obj); // Compares memory addresses
}

The default behavior compares object references. To compare based on internal state, we override equals().

class GameTile {
    int value;
    String color;

    public GameTile(int value, String color) {
        this.value = value;
        this.color = color;
    }

    @Override
    public boolean equals(Object otherObj) {
        // Check if it's the same object
        if (this == otherObj) {
            return true;
        }
        // Check for null or incompatible type
        if (otherObj == null || !(otherObj instanceof GameTile)) {
            return false;
        }
        GameTile otherTile = (GameTile) otherObj;
        // Compare based on value attribute
        return value == otherTile.value;
    }
}

Common override pattern:

  1. Return true if comparing the same object instance.
  2. Return false if the arrgument is null.
  3. Return false if the argument is not of the correct type.
  4. Perform field-by-field comparison as required.

Limitation: equals() only checks for equality, not relative ordering (greater than/less than).

Implementing the Comparable Interface

The java.lang.Comparable interface defines a natural ordering for a class. Implement compareTo().

public interface Comparable<T> {
    // Returns:
    // Negative: this object < specified object
    // Zero: this object == specified object
    // Positive: this object > specified object
    int compareTo(T other);
}
class GameTile implements Comparable<GameTile> {
    int value;
    String color;

    public GameTile(int value, String color) {
        this.value = value;
        this.color = color;
    }

    @Override
    public int compareTo(GameTile otherTile) {
        if (otherTile == null) {
            return 1; // Treat non-null as greater than null
        }
        return this.value - otherTile.value;
    }
}

Usage example:

public class ComparisonDemo {
    public static void main(String[] args) {
        GameTile tile1 = new GameTile(5, "Red");
        GameTile tile2 = new GameTile(12, "Blue");
        GameTile tile3 = new GameTile(5, "Red");

        System.out.println(tile1.compareTo(tile3)); // 0 (equal)
        System.out.println(tile2.compareTo(tile3)); // Positive (tile2 greater)
        System.out.println(tile1.compareTo(tile2)); // Negative (tile1 less)
    }
}

Creating a Custom Comparator

Define a separate class implementing java.util.Comparator to encapsulate a specific comparison logic.

import java.util.Comparator;

public interface Comparator<T> {
    // Returns:
    // Negative: first object < second object
    // Zero: first object == second object
    // Positive: first object > second object
    int compare(T obj1, T obj2);
}
class TileValueComparator implements Comparator<GameTile> {
    // Compares based on value, ignoring color.
    // Treats null as the smallest possible value.
    @Override
    public int compare(GameTile tileA, GameTile tileB) {
        if (tileA == tileB) {
            return 0;
        }
        if (tileA == null) {
            return -1;
        }
        if (tileB == null) {
            return 1;
        }
        return tileA.value - tileB.value;
    }
}

Usage example:

import java.util.Comparator;

public class ComparisonDemo {
    public static void main(String[] args) {
        GameTile tile1 = new GameTile(5, "Red");
        GameTile tile2 = new GameTile(12, "Blue");
        GameTile tile3 = new GameTile(5, "Red");

        Comparator<GameTile> comp = new TileValueComparator();
        System.out.println(comp.compare(tile1, tile3)); // 0
        System.out.println(comp.compare(tile2, tile3)); // Positive
        System.out.println(comp.compare(tile1, tile2)); // Negative
    }
}

Comparison of Approaches

  • Object.equals(): Available in all classes by inheritance. Simple to override but limited to equality checks.
  • Comparable.compareTo(): Defines a natural, internal ordering for a class. Requires modifyinng the class itself.
  • Comparator.compare(): Provides external, flexible comparison logic without modifying the original class. Useful for multiple ordering criteria.

Tags: java Object Comparison Comparable comparator equals method

Posted on Fri, 21 Aug 2026 16:37:47 +0000 by raimis100