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 |