W3docs

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 characters

equals 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 null

Why == 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.

ExpressionResultWhy
"java" == "java"trueBoth refer to the same interned literal
"java" == new String("java")falsenew creates a distinct object
"java".equals(new String("java"))trueCompares 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");   // true

It 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 later

A 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 (AZ) 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.

java— editable, runs on the server

What to take from the run:

  • a == b prints false even though both strings read "java", because new String("java") is a separate object — proof that == compares identity, not text.
  • a.equals(b) prints true: equals looks at the characters, which is what you almost always mean by "the same string".
  • a == c prints true only because both are literals sharing one interned object — this accidental success is exactly why == lures beginners into a bug.
  • equalsIgnoreCase prints true for "Java" vs "JAVA", while compareTo returns 0 for identical text and a non-zero sign (-1 for apple before banana) when they differ.
  • Objects.equals(null, "x") prints false instead of throwing, and the sorted array prints [Cherry, apple, banana] — uppercase C (code point 67) sorts before lowercase letters (code point 97+).

Practice

Practice

Why does the expression new String('hi') == 'hi' evaluate to false in Java?