How to Compare Strings in Java
Compare Java strings with equals, equalsIgnoreCase, compareTo, and avoid common pitfalls with ==.
How to Compare Strings in Java
Comparing two String values in Java is one of the first things a beginner gets wrong, because the == operator quietly compares references instead of contents. This chapter shows the correct, idiomatic ways to test strings for equality and ordering — equals, equalsIgnoreCase, compareTo, and the null-safe Objects.equals — and explains exactly when each one is the right tool.
Equality of contents with equals
To check whether two strings hold the same characters, call equals:
String a = "hello";
String b = new String("hello");
boolean same = a.equals(b); // true — same charactersequals walks the two character sequences and returns true only when they have the same length and the same characters in the same order. It is the method you want 99% of the time you ask "are these two strings the same text?".
A common defensive trick is to call equals on a string literal so the receiver is never null:
if ("yes".equals(userInput)) { ... } // safe even if userInput is nullWhy == is the classic trap
== does not look at characters at all — it asks "are these the exact same object in memory?". Because the compiler interns string literals (stores one shared copy in a pool), two identical literals can happen to be ==, which lulls people into thinking == compares text. It does not: the moment a string comes from new, user input, or concatenation at runtime, == returns false even for identical text.
| Expression | Result | Why |
|---|---|---|
"java" == "java" | true | Both refer to the same interned literal |
"java" == new String("java") | false | new creates a distinct object |
"java".equals(new String("java")) | true | Compares contents, not identity |
Rule of thumb: never use == to compare strings. Reach for equals.
Case-insensitive comparison with equalsIgnoreCase
When case should not matter — usernames, file extensions, header names — use equalsIgnoreCase:
"Java".equalsIgnoreCase("JAVA"); // trueIt applies the same character-by-character logic as equals after folding case, so "README".equalsIgnoreCase("readme") is true.
Ordering with compareTo
To sort or rank strings rather than just test equality, use compareTo, which returns the sign of the lexicographic (dictionary-style) difference:
"apple".compareTo("banana"); // negative — apple comes first
"apple".compareTo("apple"); // 0 — equal
"banana".compareTo("apple"); // positive — banana comes laterA negative result means the receiver sorts before the argument, 0 means equal, positive means after. There is a compareToIgnoreCase variant, and String.CASE_INSENSITIVE_ORDER for use as a Comparator. Note that the default ordering is by Unicode code point, so all uppercase letters (A–Z) sort before all lowercase letters.
A worked example
This program exercises every approach side by side so you can see precisely how each one behaves.
What to take from the run:
a == bprintsfalseeven though both strings read "java", becausenew String("java")is a separate object — proof that==compares identity, not text.a.equals(b)printstrue:equalslooks at the characters, which is what you almost always mean by "the same string".a == cprintstrueonly because both are literals sharing one interned object — this accidental success is exactly why==lures beginners into a bug.equalsIgnoreCaseprintstruefor"Java"vs"JAVA", whilecompareToreturns0for identical text and a non-zero sign (-1for apple before banana) when they differ.Objects.equals(null, "x")printsfalseinstead of throwing, and the sorted array prints[Cherry, apple, banana]— uppercaseC(code point 67) sorts before lowercase letters (code point 97+).
Practice
Why does the expression new String('hi') == 'hi' evaluate to false in Java?