β `equals()` vs `==` in Java - Complete Guide
Understanding object comparison and equality in Java
π― Why This Matters
Section titled βπ― Why This Mattersβ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().

π Comparison Table
Section titled βπ Comparison Tableβ| Feature | == Operator | equals() Method |
|---|---|---|
| Purpose | Compares references (memory addresses) | Compares content/data (logical equality) |
| Usage | Used for primitive types and object references | Used to compare the actual content of objects |
| Default Behavior | For objects, compares memory addresses | Default in Object class also compares memory addresses, but you can override it |
| Example (primitive) | int a = 5; int b = 5; a == b β true | Not applicable for primitives |
| Example (object) | obj1 == obj2 β true if same memory | obj1.equals(obj2) β true if logically equal |
| Performance | Very fast (direct memory comparison) | Can be slower (may involve method calls) |
| Override | Cannot be overridden | Can be overridden for custom logic |
π Basic Examples
Section titled βπ Basic ExamplesβPrimitive Comparison
Section titled βPrimitive Comparisonβ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) }}Object Reference Comparison
Section titled βObject Reference Comparisonβ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 }}π§ Implementing Custom equals() Method
Section titled βπ§ Implementing Custom equals() Methodβ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:
HashSetHashMapHashtableLinkedHashMapConcurrentHashMap
Example
Section titled βExampleβ@Overridepublic int hashCode() { return Objects.hash(name, age);}π For immutable fields like
nameandage, 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! }}π Key Takeaway:
Section titled βπ Key Takeaway:βContract:
Ifa.equals(b)istrue, thena.hashCode() == b.hashCode()must also be true.