Skip to content
Dev Dump

βœ… `equals()` vs `==` in Java - Complete Guide

Understanding object comparison and equality in Java

Understanding the difference between == and equals() is fundamental for Java programming. It affects:

  • Object comparison logic
  • Collection behavior (HashSet, HashMap)
  • Performance of equality checks
  • Bug prevention in object comparisons
  • Interview success - this is a very common question

πŸ’‘ Interview Focus: This topic tests your understanding of object identity vs equality, and contract compliance between equals() and hashCode().

object comparison

Feature== Operatorequals() Method
PurposeCompares references (memory addresses)Compares content/data (logical equality)
UsageUsed for primitive types and object referencesUsed to compare the actual content of objects
Default BehaviorFor objects, compares memory addressesDefault in Object class also compares memory addresses, but you can override it
Example (primitive)int a = 5; int b = 5; a == b β†’ trueNot applicable for primitives
Example (object)obj1 == obj2 β†’ true if same memoryobj1.equals(obj2) β†’ true if logically equal
PerformanceVery fast (direct memory comparison)Can be slower (may involve method calls)
OverrideCannot be overriddenCan be overridden for custom logic
public class PrimitiveComparison {
public static void main(String[] args) {
int a = 5;
int b = 5;
int c = 10;
System.out.println(a == b); // true (same value)
System.out.println(a == c); // false (different values)
// For primitives, == is the only way to compare
double d1 = 3.14;
double d2 = 3.14;
System.out.println(d1 == d2); // true
// Floating point precision issues
double d3 = 0.1 + 0.2;
double d4 = 0.3;
System.out.println(d3 == d4); // false! (0.30000000000000004 != 0.3)
System.out.println(Math.abs(d3 - d4) < 0.0001); // true (use tolerance)
}
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ObjectComparison {
public static void main(String[] args) {
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
Person p3 = p1; // Same reference
System.out.println(p1 == p2); // false β†’ different objects
System.out.println(p1 == p3); // true β†’ same reference
System.out.println(p1.equals(p2)); // false β†’ not overridden, so still compares references
// String comparison
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1 == s2); // true β†’ string pool
System.out.println(s1 == s3); // false β†’ different objects
System.out.println(s1.equals(s3)); // true β†’ content comparison
}
}

Now, if we override equals(), it becomes logical comparison:

class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
// Check if same reference
if (this == o) return true;
// Check if null or different class
if (o == null || getClass() != o.getClass()) return false;
// Cast and compare fields
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}

βœ… Always override hashCode() when you override equals()

Section titled β€œβœ… Always override hashCode() when you override equals()”

If two objects are equal (according to .equals()), they must have the same hash code if used in hash-based collections like:

  • HashSet
  • HashMap
  • Hashtable
  • LinkedHashMap
  • ConcurrentHashMap
@Override
public int hashCode() {
return Objects.hash(name, age);
}

πŸ”’ For immutable fields like name and age, this is safe and efficient.

πŸ”₯ What happens if you override equals() but not hashCode()?

Section titled β€œπŸ”₯ What happens if you override equals() but not hashCode()?”

❌ Example of Faulty Behavior

public class HashCodeExample {
public static void main(String[] args) {
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
System.out.println("p1.equals(p2): " + p1.equals(p2)); // true
Set<Person> set = new HashSet<>();
set.add(p1);
set.add(p2); // Should NOT be added if equals() says they are same
System.out.println("Set size: " + set.size()); // Prints 2! (should be 1)
System.out.println("p1.hashCode(): " + p1.hashCode());
System.out.println("p2.hashCode(): " + p2.hashCode()); // Different hash codes!
}
}

Contract:
If a.equals(b) is true, then a.hashCode() == b.hashCode() must also be true.