Java String Comparison: == vs equals() vs compareTo()
Introduction
Comparing strings is one of the most frequent operations in any program - checking a password, matching a command, sorting names. Java gives you several ways to do it, and choosing the wrong one is one of the most common Java bugs. This tutorial explains Java string comparison with ==, equals() and compareTo(). We will start with why
(Note - This tutorial builds on the Java String poolClick to read tutorial: Java String Pool: String Literals vs new String(), which explains why
OUTPUT of the above code
The user typed exactly
OUTPUT of the above code
Explanation of the code
Comparing with null safely
Calling
OUTPUT of the above code
compareTo() - which string comes first?
Definition of
Where,
OUTPUT of the above code
Explanation of the code
Sorting strings
Sorting uses the same comparison.
OUTPUT of the above code
For sorting by any rule - by length, by surname, in reverse - see The Complete Java 8 Comparator TutorialClick to read The Complete Java 8 Comparator Tutorial.
Which one should you use?
== is the wrong way to compare strings. We will then compare contents with equals() and equalsIgnoreCase(), and handle null safely. Next we will put strings in order with compareTo(), and see how it decides which string comes first. Lastly, we will sort strings, and summarize which method to use when.(Note - This tutorial builds on the Java String poolClick to read tutorial: Java String Pool: String Literals vs new String(), which explains why
== sometimes appears to work.)
== compares references, not contents
For objects, == checks whether two variables refer to the same object in memory. Two different String objects with exactly the same characters are not ==. Because string literals are pooled, == often happens to work in small tests - and then fails when one string comes from user input, a file, or a calculation.
Why == is wrong for comparing strings
//DoubleEqualsTrap.java
import java.util.Scanner;
public class DoubleEqualsTrap {
public static void main(String[] args) {
String expected = "yes";
String literal = "yes";
System.out.println("literal == expected : " + (literal == expected));
Scanner scanner = new Scanner(System.in);
System.out.print("Continue? ");
String answer = scanner.nextLine();
System.out.println("answer == expected : " + (answer == expected));
System.out.println("answer.equals(expected) : " + answer.equals(expected));
}
}
literal == expected : true Continue? yes answer == expected : false answer.equals(expected) : true
yes, but == said false - the typed text is a new String object, not the pooled literal. Use == with strings only to check for null (s == null).
equals() and equalsIgnoreCase()
equals() compares the contents of two strings, character by character. It returns true only if both have the same length and the same characters in the same order - including case and spaces. equalsIgnoreCase() does the same, but treats upper- and lower-case letters as equal.
Comparing contents with equals() and equalsIgnoreCase()
//EqualsDemo.java
public class EqualsDemo {
public static void main(String[] args) {
String a = "Java";
String b = new String("Java");
String upper = "JAVA";
String padded = " Java ";
System.out.println("a.equals(b) : " + a.equals(b));
System.out.println("a.equals(upper) : " + a.equals(upper));
System.out.println("a.equalsIgnoreCase(upper) : " + a.equalsIgnoreCase(upper));
System.out.println("a.equals(padded) : " + a.equals(padded));
System.out.println("a.equals(padded.strip()) : " + a.equals(padded.strip()));
System.out.println("\"\".equals(\"\") : " + "".equals(""));
}
}
a.equals(b) : true
a.equals(upper) : false
a.equalsIgnoreCase(upper) : true
a.equals(padded) : false
a.equals(padded.strip()) : true
"".equals("") : true
aandbare different objects but have equal contents, soequals()returnstrue.equals()is case-sensitive;equalsIgnoreCase()is not.- Leading and trailing spaces make strings unequal. User input is often cleaned with
strip()(or the oldertrim()) before comparing.
equals() on a null variable throws a NullPointerException. Two common ways to avoid it are to call equals() on the literal - which can never be null - or to use Objects.equals(), which handles null on either side.
null-safe string comparison
//NullSafeEquals.java
import java.util.Objects;
public class NullSafeEquals {
public static void main(String[] args) {
String command = null;
System.out.println("\"quit\".equals(command) : " + "quit".equals(command));
System.out.println("Objects.equals(command, x) : " + Objects.equals(command, "quit"));
System.out.println("Objects.equals(null, null) : " + Objects.equals(null, null));
try {
System.out.println(command.equals("quit"));
} catch (NullPointerException e) {
System.out.println("command.equals(...) threw a NullPointerException");
}
}
}
"quit".equals(command) : false Objects.equals(command, x) : false Objects.equals(null, null) : true command.equals(...) threw a NullPointerException
equals() only says whether two strings are the same. To put strings in order, use compareTo().Definition of
compareTo() in java.lang.String is -public int compareTo(String anotherString)- it returns a negative number if this string comes before the other, zero if they are equal, and a positive number if it comes after.
- the strings are compared character by character, from the start. At the first position where they differ, the result is the difference between the two characters' Unicode values.
- if one string is a prefix of the other, the shorter one comes first, and the result is the difference in length.
compareToIgnoreCase() works the same way, but ignores case.
Ordering strings with compareTo()
//CompareToDemo.java
public class CompareToDemo {
public static void main(String[] args) {
System.out.println("\"apple\".compareTo(\"banana\") = " + "apple".compareTo("banana"));
System.out.println("\"cherry\".compareTo(\"apple\") = " + "cherry".compareTo("apple"));
System.out.println("\"Java\".compareTo(\"Java\") = " + "Java".compareTo("Java"));
System.out.println("\"Java\".compareTo(\"JavaScript\") = " + "Java".compareTo("JavaScript"));
System.out.println("\"Zebra\".compareTo(\"apple\") = " + "Zebra".compareTo("apple"));
System.out.println("\"Zebra\".compareToIgnoreCase(\"apple\") = " + "Zebra".compareToIgnoreCase("apple"));
System.out.println("\"10\".compareTo(\"9\") = " + "10".compareTo("9"));
String first = "Harry", second = "Ethan";
if (first.compareTo(second) < 0) {
System.out.println(first + " comes before " + second);
} else {
System.out.println(second + " comes before " + first);
}
}
}
"apple".compareTo("banana") = -1
"cherry".compareTo("apple") = 2
"Java".compareTo("Java") = 0
"Java".compareTo("JavaScript") = -6
"Zebra".compareTo("apple") = -7
"Zebra".compareToIgnoreCase("apple") = 25
"10".compareTo("9") = -8
Ethan comes before Harry
'a'(97) and'b'(98) differ by 1, so"apple"comes 1 before"banana"."Java"is a prefix of"JavaScript", so it comes first, and the result is the length difference, -6.- Case matters: all capital letters come before all lower-case letters in Unicode, so
"Zebra"comes before"apple".compareToIgnoreCase()gives the dictionary order. - Numbers stored as strings are compared as text, so
"10"comes before"9"(the character'1'is before'9'). Convert them to numbers to compare their values. - To use the result, test its sign -
< 0,== 0or> 0.
Arrays.sort() and Collections.sort() order strings by compareTo() - their natural order - unless you pass a different Comparator.
Sorting strings in natural and case-insensitive order
//SortingStrings.java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SortingStrings {
public static void main(String[] args) {
List<String> names = new ArrayList<>(List.of("tom", "Nancy", "ethan", "Harry", "deborah"));
names.sort(null); // natural order (compareTo)
System.out.println("Natural : " + names);
names.sort(String.CASE_INSENSITIVE_ORDER); // compareToIgnoreCase
System.out.println("Ignore case : " + names);
names.sort(Comparator.comparing(String::length)); // by length
System.out.println("By length : " + names);
}
}
Natural : [Harry, Nancy, deborah, ethan, tom] Ignore case : [deborah, ethan, Harry, Nancy, tom] By length : [tom, ethan, Harry, Nancy, deborah]
a.equals(b)- are the contents the same? The default way to compare strings.a.equalsIgnoreCase(b)- the same, ignoring case. Good for commands and answers such as "yes"/"YES"."literal".equals(a)orObjects.equals(a, b)- whenamay benull.a.compareTo(b)- which comes first? For ordering and sorting.a == b- only to check whetheraisnull, or (rarely) whether two variables refer to the very same object.
== compares references, so it fails for equal strings which are different objects - such as user input. We then compared contents with equals() and equalsIgnoreCase(), and handled null safely with the literal-first style and Objects.equals(). Next we put strings in order with compareTo(), and saw how it compares characters and handles prefixes and case. We then sorted strings in natural and case-insensitive order. Lastly, we summarized which comparison to use when. In the next tutorial, we will go through the essential String methodsClick to read tutorial: Essential Java String Methods with Examples.Java Fundamentals Tutorials
Java String Pool: String Literals vs new String()Click to read tutorial: Java String Pool: String Literals vs new String() Essential Java String Methods with ExamplesClick to read tutorial: Essential Java String Methods with Examples Java String Basics and Why Strings Are ImmutableClick to read tutorial: Java String Basics and Why Strings Are Immutable String vs StringBuilder vs StringBuffer in JavaClick to read tutorial: String vs StringBuilder vs StringBuffer in Java Java Text Blocks: Multi-line Strings with ExamplesClick to read tutorial: Java Text Blocks: Multi-line Strings with Examples Common Java String Programs with ExamplesClick to read tutorial: Common Java String Programs with Examples What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses
Java String Pool: String Literals vs new String()Click to read tutorial: Java String Pool: String Literals vs new String() Essential Java String Methods with ExamplesClick to read tutorial: Essential Java String Methods with Examples Java String Basics and Why Strings Are ImmutableClick to read tutorial: Java String Basics and Why Strings Are Immutable String vs StringBuilder vs StringBuffer in JavaClick to read tutorial: String vs StringBuilder vs StringBuffer in Java Java Text Blocks: Multi-line Strings with ExamplesClick to read tutorial: Java Text Blocks: Multi-line Strings with Examples Common Java String Programs with ExamplesClick to read tutorial: Common Java String Programs with Examples What is Java? History, Features, Editions and UsesClick to read tutorial: What is Java? History, Features, Editions and Uses