Leepoint Java Reference Notes on the Java language and its standard library.

Comparing strings

The single most common mistake in beginner Java, and the reason it is so persistent.

Use equals, not ==.

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

a == b            // false, two different objects
a.equals(b)       // true, same characters

== compares references: whether two variables point at the same object in memory. equals compares contents. For strings you almost always want the second.

Why the wrong version often works

This is what makes the bug so durable. Try it with literals and == appears to be fine:

String a = "hello";
String b = "hello";
a == b            // true

Both variables refer to the same object, because the compiler puts identical string literals in a shared pool and reuses them. That is an optimisation, not a guarantee about comparison. The moment a string arrives from user input, a file, a network response or a StringBuilder, it is a new object and == returns false.

So the code passes every test written with literals and fails the first time it meets real data. Always use equals.

Ordering, not just equality

equals answers yes or no. For sorting you need compareTo, which returns a negative number, zero, or a positive number:

"apple".compareTo("banana")    // negative. Apple sorts first
"banana".compareTo("apple")    // positive
"apple".compareTo("apple")     // zero

Only the sign is meaningful. Do not rely on the magnitude; it is not specified.

compareTo compares by Unicode code point, which means uppercase sorts before lowercase, "Zebra" comes before "apple". For human-facing ordering that is wrong, and String.CASE_INSENSITIVE_ORDER or a Collator is what you want.

Ignoring case

a.equalsIgnoreCase(b)
a.compareToIgnoreCase(b)

These handle the common case. For text in languages with rules the ASCII assumptions do not cover, Turkish dotted and dotless i is the standard example, use a Collator from java.text.

Null

a.equals(b) throws a NullPointerException if a is null. Two ways round it:

Objects.equals(a, b)          // handles either or both being null
"expected".equals(input)      // literal first, never null

The second is an old habit worth keeping when comparing against a constant.

Summary

Question Use
Same contents? equals
Same contents, ignoring case? equalsIgnoreCase
Which sorts first? compareTo
Same object? ==, rarely what you want
Either might be null? Objects.equals