EMZETT.
Login

Comparison Operators

In short: Operators that compare two values and return a boolean (true/false): == != < > <= >=.

In more detail: Important trap in Java: == compares the reference for objects (e.g. String), not the content — two strings that are equal in content can still return false with == if they’re different objects in memory. For comparing the content of objects, .equals() should be used instead.

In Depth

String a = "hello";
String b = "hello";
String c = new String("hello");
 
System.out.println(a == b);        // true - Java automatically "interns" identical string literals
System.out.println(a == c);        // false - c is a separate object on the heap
System.out.println(a.equals(c));   // true - content comparison, independent of object identity
 
Integer x = 127, y = 127;
Integer p = 200, q = 200;
System.out.println(x == y); // true - Integer cache for -128..127
System.out.println(p == q); // false! Outside the cache they're different objects

The Integer cache case is especially tricky: Java automatically caches Integer objects for small values (-128 to 127) for performance reasons, which makes == comparisons “work” by coincidence in this range but not outside it — a classic bug that goes undetected in tests with small numbers and only shows up in production with larger values. Rule of thumb with no exceptions: for primitive types (int, double, boolean, …), == is correct and the only possible comparison; for objects (String, Integer, your own classes, …), always use .equals(), never ==.

Relational operators for different types

< > <= >= in Java only work on primitive numeric types (int, double, char, …), NOT directly on objects like String — "apple" < "banana" simply doesn’t compile. For lexicographic comparison of strings, there’s compareTo() instead:

String a = "apple", b = "banana";
System.out.println(a.compareTo(b)); // negative, since "apple" comes alphabetically before "banana"
System.out.println(a.compareTo(a)); // 0 - identical

The sign of the return value counts, not the exact numeric value — negative means “comes before”, positive “comes after”, 0 means “equal”. This compareTo() pattern runs throughout all of Java: the Comparable interface (for a class’s “natural” sort order) and Comparator (for custom sort orders) both build exactly on this.

Overriding equals() yourself

For your own classes, .equals() without a custom implementation by default returns the same result as == (reference comparison), since Object.equals() does exactly that. For a true content comparison, equals() (and, for consistency, also always hashCode()) has to be overridden:

class Point {
    int x, y;
 
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Point p)) return false;
        return x == p.x && y == p.y;
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

If equals() is overridden but hashCode() is forgotten (or vice versa), HashSet/HashMap behave inconsistently — two objects that are equal according to equals() can then still be treated as “different” because they have different hash codes.

See also: Operators, Logical Operators, if Statement