Hero Background

Next-Gen App & Browser Testing Cloud

Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Next-Gen App & Browser Testing Cloud

Write a Java program to compare two strings?

To compare two strings in Java, use equals() for an exact content match, equalsIgnoreCase() to ignore case, compareTo() or compareToIgnoreCase() for lexicographic ordering, and Objects.equals() when either value might be null. Avoid the == operator for content checks: it compares object references, not characters, so two strings with identical text can still evaluate to false. The example program below demonstrates every method with its output.

Methods to Compare Two Strings in Java

A String in Java is an immutable sequence of characters, so a comparison never changes either operand; it only reports how the two values relate. These are the standard ways to compare them:

  • equals(Object): compares the full character sequence and returns a boolean. It is case-sensitive, so "apple".equals("Apple") is false. This is the default choice for checking whether two strings hold the same text.
  • equalsIgnoreCase(String): the same content check as equals() but case-insensitive, so "apple".equalsIgnoreCase("APPLE") returns true. Use it for user input, file names, or tokens where case should not matter.
  • compareTo(String): performs a lexicographic (dictionary-order) comparison and returns an int rather than a boolean: 0 when equal, a negative value when the calling string sorts first, and a positive value when it sorts later. The magnitude equals the Unicode difference of the first mismatched character.
  • compareToIgnoreCase(String): identical to compareTo() but folds case before comparing, so "apple".compareToIgnoreCase("APPLE") returns 0. Useful for case-insensitive sorting.
  • Objects.equals(Object, Object): a null-safe wrapper from java.util.Objects. It returns true for two nulls, false if only one is null, and otherwise delegates to equals(), so it never throws a NullPointerException.
  • contentEquals(CharSequence): compares a String against any CharSequence, including a StringBuilder or StringBuffer. It is the right call when the other value is not itself a String.
  • == operator: compares references, not content. It is true only when both variables point to the exact same object in memory, which makes it unsuitable for content comparison (explained below).

String Comparison Methods at a Glance

The table below summarizes what each approach compares and what it returns, so you can pick the right one before writing a single line of code.

MethodComparesReturns
equals()Content, case-sensitiveboolean
equalsIgnoreCase()Content, case-insensitiveboolean
compareTo()Lexicographic order, case-sensitiveint (0, <0, >0)
compareToIgnoreCase()Lexicographic order, case-foldedint (0, <0, >0)
Objects.equals()Content, null-safeboolean
contentEquals()Content vs any CharSequenceboolean
==Reference (same object), not contentboolean

Complete Java Program to Compare Two Strings

The following program is fully compilable and demonstrates each method on the same inputs so you can see exactly how their results differ.

import java.util.Objects;

public class CompareStrings {
    public static void main(String[] args) {
        String s1 = "apple";
        String s2 = "apple";              // same literal, pooled
        String s3 = new String("apple");  // new object, same content

        // 1. equals() - content, case-sensitive
        System.out.println("equals (apple, apple): " + s1.equals(s2));
        System.out.println("equals (apple, Apple): " + s1.equals("Apple"));

        // 2. equalsIgnoreCase() - content, ignores case
        System.out.println("equalsIgnoreCase (apple, APPLE): " + s1.equalsIgnoreCase("APPLE"));

        // 3. compareTo() - lexicographic, returns int
        System.out.println("compareTo (apple, apple): " + s1.compareTo("apple"));
        System.out.println("compareTo (apple, Apple): " + s1.compareTo("Apple"));
        System.out.println("compareTo (apple, banana): " + s1.compareTo("banana"));

        // 4. compareToIgnoreCase() - lexicographic, case-folded
        System.out.println("compareToIgnoreCase (apple, APPLE): " + s1.compareToIgnoreCase("APPLE"));

        // 5. == operator - reference, NOT content
        System.out.println("== (s1, s2 literals): " + (s1 == s2));
        System.out.println("== (s1, s3 new String): " + (s1 == s3));
        System.out.println("equals (s1, s3): " + s1.equals(s3));

        // 6. Objects.equals() - null-safe content check
        System.out.println("Objects.equals (apple, null): " + Objects.equals(s1, null));
        System.out.println("Objects.equals (null, null): " + Objects.equals(null, null));

        // 7. contentEquals() - String vs CharSequence
        System.out.println("contentEquals (apple, StringBuilder apple): "
                + s1.contentEquals(new StringBuilder("apple")));
    }
}

Output:

equals (apple, apple): true
equals (apple, Apple): false
equalsIgnoreCase (apple, APPLE): true
compareTo (apple, apple): 0
compareTo (apple, Apple): 32
compareTo (apple, banana): -1
compareToIgnoreCase (apple, APPLE): 0
== (s1, s2 literals): true
== (s1, s3 new String): false
equals (s1, s3): true
Objects.equals (apple, null): false
Objects.equals (null, null): true
contentEquals (apple, StringBuilder apple): true

Notice that compareTo("apple", "Apple") returns 32, the Unicode gap between lowercase 'a' (97) and uppercase 'A' (65), while compareTo("apple", "banana") returns -1 because 'a' (97) precedes 'b' (98). The two == lines are the most instructive: identical literals share one pooled object and report true, but s3 built with new String() is a separate object and reports false, even though equals() confirms the content is the same.

Why == Is Not Reliable for Strings

The == operator answers a different question than most developers expect. It checks whether two variables refer to the same object, not whether they hold the same characters. With strings, the result depends on how each value was created:

  • String constant pool: Java stores string literals in a shared pool. Two identical literals such as "apple" and "apple" are deduplicated into one object, so == happens to return true. This is a memory optimization, not a content guarantee.
  • new String() breaks the coincidence: calling new String("apple") forces a fresh object on the heap. Now == returns false against the pooled literal even though both contain "apple". Values read at runtime, for example from input, files, or network responses, are typically not pooled either.
  • intern() restores pooling: s3.intern() returns the canonical pooled reference, so s1 == s3.intern() is true again. This confirms == is purely about object identity.
  • The takeaway: because == "works" with literals during quick tests, the bug often hides until production data flows in. Always use equals() (or Objects.equals() for null safety) to compare string content.

When to Use Which Method

  • Exact content match: use equals(). It is the everyday choice for "are these two strings the same text?"
  • Case-insensitive match: use equalsIgnoreCase() for emails, usernames, command keywords, and other case-agnostic input.
  • Sorting or ordering: use compareTo() (or compareToIgnoreCase()), since collections, comparators, and binary searches rely on its int ordering result.
  • One side may be null: use Objects.equals() to sidestep NullPointerException without manual null checks.
  • Comparing against a builder: use contentEquals() when the other operand is a StringBuilder, StringBuffer, or any CharSequence.
  • Reference identity: reserve == for the rare case where you genuinely need to know two variables point to the same object, never for comparing text.

String comparison logic also shows up constantly in automated UI tests, where assertions verify that on-screen text matches expected values. When you run such Java tests across browsers and operating systems on the TestMu AI Selenium Automation cloud, the same equals() and equalsIgnoreCase() patterns drive your assertions, so getting them right locally keeps your suite reliable at scale.

Frequently Asked Questions

What is the difference between == and .equals() for strings in Java?

The == operator compares references, meaning it checks whether two variables point to the same object in memory. The .equals() method compares the actual character content. Two strings with identical text can return false with == if they are separate objects, but .equals() always returns true when the content matches. For content comparison, always use .equals().

How do I compare two strings while ignoring case in Java?

Use equalsIgnoreCase() for a true or false content check that ignores upper and lower case, for example "Apple".equalsIgnoreCase("apple") returns true. If you need ordering instead of equality, use compareToIgnoreCase(), which returns an int and treats the two strings as equal in case-folded form.

What does compareTo() return when comparing two strings?

compareTo() returns an int based on lexicographic (dictionary) order. It returns 0 when the strings are equal, a negative number when the calling string comes before the argument, and a positive number when it comes after. The magnitude is the Unicode difference of the first non-matching character.

Why does == sometimes return true for equal strings?

String literals are stored in the string constant pool, so two identical literals reference the same object and == happens to return true. As soon as one string is created with new String(), it becomes a separate object and == returns false even though the content matches. This coincidence is exactly why == is unsafe for content checks.

How do I compare two strings safely when one might be null?

Use Objects.equals(a, b) from java.util.Objects. It returns true when both are null, false when only one is null, and otherwise delegates to equals(). This avoids the NullPointerException you would get from calling a.equals(b) when a is null.

What is the difference between equals() and contentEquals() in Java?

equals() only returns true when the argument is also a String with matching content. contentEquals() compares a String against any CharSequence, such as a StringBuilder or StringBuffer, so "apple".contentEquals(new StringBuilder("apple")) returns true, whereas equals() on the same StringBuilder would return false.

Related Questions

Test Your Website on 3000+ Browsers

Get 100 minutes of automation test minutes FREE!!

Test Now...

KaneAI - Testing Assistant

World’s first AI-Native E2E testing agent.

...

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests