Java String equals: Compare Strings Correctly
java string equals: Learn how to compare strings in Java using equals, equalsIgnoreCase, and related methods, and avoid common pitfalls with == and null handling.
Comparing strings in Java is a common source of subtle bugs if you rely on the == operator instead of the equals method. The java string equals method compares the actual character sequence, while == compares object references. This article explains how to use equals correctly, when to use related methods, and how to avoid null-related failures.
The Difference Between == and equals
The == operator in Java checks whether two references point to the same object in memory. It does not compare the content of the strings. For example, two strings created with the new keyword will always be distinct objects, even if they contain identical characters:
String a = new String("test"); String b = new String("test"); System.out.println(a == b); // false System.out.println(a.equals(b)); // true
String literals, however, are interned by the JVM, so two literals with the same value may actually be the same reference:
String c = "test"; String d = "test"; System.out.println(c == d); // true (due to interning) System.out.println(c.equals(d)); // true
This behavior makes == unreliable for content comparison. The only safe way to compare string values is to use equals (or a related method).
How String.equals Works
The equals method in the String class overrides Object.equals. It first checks if the argument is an instance of String. If not, it returns false. Then it compares the lengths and each character sequentially. The comparison is case-sensitive, so "Java" and "java" are not equal.
String s1 = "Java"; String s2 = "Java"; String s3 = "java"; System.out.println(s1.equals(s2)); // true System.out.println(s1.equals(s3)); // false
Because equals performs a character-by-character scan, its time complexity is O(n) in the length of the string. For most applications this is negligible, but it is worth keeping in mind when comparing very large strings in tight loops.
Comparing Strings with equalsIgnoreCase
If you need to compare strings without regard to case, use equalsIgnoreCase instead of converting both strings to lowercase and then calling equals. The equalsIgnoreCase method performs case-insensitive comparison and handles Unicode case folding correctly, which is more robust than manual toLowerCase() calls.
String greeting = "Hello"; System.out.println(greeting.equalsIgnoreCase("HELLO")); // true System.out.println(greeting.equalsIgnoreCase("hello")); // true System.out.println(greeting.equalsIgnoreCase("Hallo")); // false
Use this method when case should not influence the result, such as when validating user input for commands or matching email addresses (though email matching has additional complexities).
Null-Safe String Comparison
A common mistake is calling equals on a reference that might be null, which throws a NullPointerException. To avoid this, you can call equals on a known non-null literal or constant, or use the Objects.equals utility method.
String input = null; // Avoid: input.equals("expected") throws NPE // Safe: call equals on the literal System.out.println("expected".equals(input)); // false // Alternatively, use Objects.equals System.out.println(Objects.equals(input, "expected")); // false
Objects.equals is null-safe for both arguments and is a good choice when both values are dynamic. It also works with any reference type, not just strings.
Comparing String Content with Other Types
If you need to compare a String with a StringBuilder or StringBuffer, the equals method will not work because those classes do not override equals to compare content. Instead, use the contentEquals method, which accepts any CharSequence:
String str = "java"; StringBuilder sb = new StringBuilder("java"); System.out.println(str.equals(sb)); // false (reference equality) System.out.println(str.contentEquals(sb)); // true
For ordering comparisons, use compareTo which returns a negative integer, zero, or a positive integer based on lexicographic order:
System.out.println("apple".compareTo("banana")); // negative System.out.println("banana".compareTo("apple")); // positive System.out.println("apple".compareTo("apple")); // zero
compareTo is case-sensitive. For case-insensitive ordering, use compareToIgnoreCase.
Performance Considerations
String equality checks are O(n), but for typical string lengths this is not a bottleneck. The == operator is O(1) because it only compares references, but it is not a substitute for content equality. If you frequently compare the same strings, consider whether you can use string interning (via intern()) to make == work, but this is rarely necessary and can cause memory overhead. In most cases, equals is the correct choice and its performance is acceptable.
When comparing a string to a constant, the JVM may optimize the call, but you should not rely on micro-optimizations without profiling. Focus on correctness first.
Common Pitfalls and How to Avoid Them
One of the most frequent errors is using == for content comparison, especially when strings are constructed at runtime. Another is forgetting that equals is case-sensitive and using it in contexts where case should be ignored. Also, comparing a String with a StringBuilder using equals returns false because the argument is not a String instance; use contentEquals instead.
Null handling is another source of bugs. Always ensure that the reference on which you call equals is not null, or use Objects.equals. A simple defensive pattern is to compare against a literal first:
if ("admin".equals(role)) { // safe even if role is null }
Finally, remember that equals performs a case-sensitive comparison. If your business logic requires case-insensitive matching, choose equalsIgnoreCase deliberately rather than converting strings to lowercase manually, which can introduce locale-specific issues.
By understanding these behaviors and applying the appropriate method, you can write string comparison code that is correct, readable, and maintainable across a wide range of Java applications.