Mastering String Comparison in Java: Difference Between “==”, equals(), compareTo(), and Best Practices

1. Introduction

Why is string comparison important in Java?

In Java programming, strings are used in many situations. Checking usernames, validating form input, and verifying API responses all require comparing strings. At this point, “how to correctly compare strings” is a common stumbling block for beginners. In particular, failing to understand the difference between the == operator and the equals() method can lead to unexpected bugs.

The danger of not understanding the difference between “==” and “equals”

Consider the following code:
String a = "apple";
String b = new String("apple");

System.out.println(a == b);       // result: false
System.out.println(a.equals(b));  // result: true
Many people are surprised by this output. Even though the strings are identical, == returns false while equals() returns true. This happens because Java treats strings as reference types, and == compares reference addresses. Understanding the correct way to compare strings directly affects the reliability and readability of your program. If you understand it properly, you can prevent bugs before they occur.

What you will learn in this article

This article explains Java string comparison from basics to practical applications. It answers questions like:
  • What is the difference between == and equals()?
  • How do you compare strings while ignoring case?
  • How do you compare strings lexicographically?
  • How do you avoid exceptions when comparing with null?
Through real-world examples, you will gain a solid understanding of correct string comparison practices.

2. Basics of Strings in Java

Strings are reference types

In Java, the String type is not a primitive (like int or boolean) but a reference type. A String variable does not store the actual characters but a reference to an object stored in heap memory. For example:
String a = "hello";
String b = "hello";
Both a and b may refer to the same "hello" literal because of Java’s string interning mechanism.

Difference between string literals and new String()

Java optimizes repeated string literals by reusing the same reference:
String s1 = "apple";
String s2 = "apple";
System.out.println(s1 == s2); // true (same literal, interned)
However, using new always creates a new object:
String s3 = new String("apple");
System.out.println(s1 == s3); // false (different references)
System.out.println(s1.equals(s3)); // true (same content)
Thus, == checks the reference and equals() checks the content.

Strings are immutable

Another key feature is that String is immutable. Once created, a string cannot be changed.
String original = "hello";
original = original + " world";
This creates a new String object rather than modifying the original.

3. Methods for Comparing Strings

Comparing references with ==

== compares object references:
String a = "Java";
String b = new String("Java");

System.out.println(a == b); // false
It should not be used for content comparison.

Comparing content with equals()

equals() is the correct way to compare string contents:
String a = "Java";
String b = new String("Java");

System.out.println(a.equals(b)); // true

Avoiding NullPointerException

String input = null;
System.out.println(input.equals("test")); // Exception!
Use the constant-first style:
System.out.println("test".equals(input)); // false, safe

Ignoring case with equalsIgnoreCase()

String a = "Hello";
String b = "hello";

System.out.println(a.equalsIgnoreCase(b)); // true

Lexicographical comparison with compareTo()

  • 0 → equal
  • Negative → caller precedes
  • Positive → caller follows
String a = "apple";
String b = "banana";

System.out.println(a.compareTo(b)); // negative

4. Practical Examples

User login checking

String inputUsername = "Naohiro";
String registeredUsername = "naohiro";

if (registeredUsername.equalsIgnoreCase(inputUsername)) {
    System.out.println("Login successful");
} else {
    System.out.println("Username does not match");
}
Passwords should always use equals() because case sensitivity is required.

Form input validation

String selectedOption = request.getParameter("plan");

if ("premium".equals(selectedOption)) {
    System.out.println("Premium plan selected.");
} else {
    System.out.println("Other plan selected.");
}

Branching logic with multiple string checks

String cmd = args[0];

if ("start".equals(cmd)) {
    startApp();
} else if ("stop".equals(cmd)) {
    stopApp();
} else {
    System.out.println("Invalid command");
}
switch (cmd) {
    case "start":
        startApp();
        break;
    case "stop":
        stopApp();
        break;
    default:
        System.out.println("Unknown command");
}

Handling null safely

String keyword = null;

if ("search".equals(keyword)) {
    System.out.println("Searching...");
}

5. Performance and Optimization

Cost of string comparisons

equals() and compareTo() compare characters internally. For long strings or repeated comparisons, this can affect performance.

Using String.intern() for performance

String a = new String("hello").intern();
String b = "hello";

System.out.println(a == b); // true
Use only when needed to avoid memory pressure.

Performance impact of equalsIgnoreCase()

String input = userInput.toLowerCase();
if ("admin".equals(input)) {
    // fast comparison
}

Using StringBuilder / StringBuffer

StringBuilder sb = new StringBuilder();
sb.append("user_");
sb.append("123");

String result = sb.toString();

if (result.equals("user_123")) {
    // comparison
}

Using caching or maps to reduce comparisons

Map<String, Runnable> commandMap = new HashMap<>();
commandMap.put("start", () -> startApp());
commandMap.put("stop", () -> stopApp());

Runnable action = commandMap.get(inputCommand);
if (action != null) {
    action.run();
}

6. FAQ

Q1. What is the difference between == and equals()?

A.
  • == compares references
  • equals() compares string content

Q2. Why does equals() throw an error when the variable is null?

String input = null;
input.equals("test"); // Exception
Use a constant-first comparison:
"test".equals(input);

Q3. How do I compare strings ignoring case?

stringA.equalsIgnoreCase(stringB);

Q4. How do I compare alphabetical order?

a.compareTo(b);

7. Conclusion

Correctly choosing the right comparison method matters

Because String is a reference type, incorrect comparison often leads to unexpected behavior. Understanding == vs equals() is essential.

Checklist

  • ==: compares references
  • equals(): compares content
  • equalsIgnoreCase(): ignore case
  • compareTo(): dictionary order
  • "constant".equals(variable): null-safe
  • Use intern() or caching for heavy comparisons

Practical and essential knowledge

String comparison appears in login checks, validation, database operations, branching logic, and many daily tasks. Knowing the correct techniques helps write safer, more reliable code. Use this guide as a reference when working with strings in Java.