Java Programs›Strings›Check Palindrome String

Check Palindrome String in Java

beginner·  Strings  ·  String

Problem

A palindrome is a string that reads the same forwards and backwards.

Given a string, determine whether it is a palindrome.

Input
madam
Output
madam is palindrome: true

Java Program

Java
public class PalindromeCheck { public static void main(String[] args) { String str = "madam"; // Build the reversed version of the string String reversed = new StringBuilder(str).reverse().toString(); // A palindrome reads the same forwards and backwards boolean isPalindrome = str.equals(reversed); System.out.println(str + " is palindrome: " + isPalindrome); } }

Output

madam is palindrome: true

Core Logic

The simplest check is to reverse the string and see if it matches the original — StringBuilder makes that a one-liner.

How It Works
  1. 1The original string is passed to new StringBuilder(str), which wraps it in a mutable buffer.
  2. 2.reverse() flips the character order in place, and .toString() converts the buffer back into a String.
  3. 3str.equals(reversed) compares the two strings character by character, not by reference.
  4. 4If every character matches its mirrored position, equals() returns true and the string is confirmed a palindrome.
For "madam", reversing it also produces "madam", so equals() returns true.
💡

Key Point: Always compare with .equals(), not == — == checks object reference, not character content, and would give the wrong answer here.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Reversing the string builds a second full copy of it, and equals() then compares both copies character by character.

Key Concepts

StringBuilderreverse()equals()

Approach 2: Manual Two-Pointer Comparison

Java
public class PalindromeCheckManual { public static void main(String[] args) { String str = "madam"; boolean isPalindrome = true; int left = 0, right = str.length() - 1; // Move left and right toward each other, comparing mirrored characters while (left < right) { if (str.charAt(left) != str.charAt(right)) { isPalindrome = false; break; // mismatch found, no need to keep checking } left++; right--; } System.out.println(str + " is palindrome: " + isPalindrome); } }

Output

madam is palindrome: true

Core Logic

No built-in reverse this time — just two pointers closing in from opposite ends, comparing characters as they go.

How It Works
  1. 1Two index variables, left and right, start at the first and last character positions.
  2. 2On each iteration, charAt(left) and charAt(right) are compared — if they differ, the string cannot be a palindrome, so isPalindrome is set to false and the loop exits early with break.
  3. 3If the characters match, left moves inward and right moves inward, narrowing the comparison window.
  4. 4The loop stops once left meets or crosses right, meaning every pair has been checked.
For "madam", the pairs checked are (m,m) and (a,a); the loop stops once left and right meet at the middle 'd' — no mismatch was found, so isPalindrome stays true.
💡

Key Point: This runs in the same O(n) time as the StringBuilder version, but uses O(1) extra space instead of O(n), since it never builds a second, reversed copy of the string — a detail interviewers often ask about directly.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: The two pointers move inward comparing characters directly on the original string, without ever building a reversed copy.

Key Concepts

two-pointer techniquecharAt()early exit with break

Approach 3: Recursive Check

Java
public class PalindromeCheckRecursive { static boolean isPalindrome(String str, int left, int right) { // Base case: pointers met or crossed, every pair matched if (left >= right) return true; // Mismatch found, not a palindrome if (str.charAt(left) != str.charAt(right)) return false; // Recurse inward, shrinking the comparison window return isPalindrome(str, left + 1, right - 1); } public static void main(String[] args) { String str = "madam"; boolean isPalindrome = isPalindrome(str, 0, str.length() - 1); System.out.println(str + " is palindrome: " + isPalindrome); } }

Output

madam is palindrome: true

Core Logic

The same two-pointer idea also works recursively: each call checks one pair of characters and hands off a slightly smaller window to the next call.

How It Works
  1. 1The base case if (left >= right) return true; fires once the pointers meet or cross, meaning every pair has matched.
  2. 2Each call compares str.charAt(left) and str.charAt(right) — a mismatch immediately returns false, short-circuiting the recursion.
  3. 3If the characters match, the call recurses inward with isPalindrome(str, left + 1, right - 1).
  4. 4The recursion naturally stops as soon as either a mismatch is found or the pointers meet.
For "madam", the calls compare (m,m) then (a,a), then hit the base case at the middle 'd', returning true all the way back up.
💡

Key Point: Functionally identical to the iterative two-pointer version, but each recursive call adds a stack frame — for very long strings, the loop-based version avoids that overhead.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Each call compares one pair and recurses inward, so up to n/2 stack frames stay alive at the deepest point.

Key Concepts

recursionbase casetwo-pointer technique

Approach 4: Java 8

Java
import java.util.stream.IntStream; public class PalindromeCheckStream { public static void main(String[] args) { String str = "madam"; // Only the first half needs checking, since each index is compared against its mirror boolean isPalindrome = IntStream.range(0, str.length() / 2) .allMatch(i -> str.charAt(i) == str.charAt(str.length() - 1 - i)); System.out.println(str + " is palindrome: " + isPalindrome); } }

Output

madam is palindrome: true

Core Logic

The two-pointer comparison can be expressed as a single stream query — every mirrored pair of characters has to match.

How It Works
  1. 1IntStream.range(0, str.length() / 2) generates indices for just the first half of the string, since each comparison covers a mirrored pair.
  2. 2.allMatch(i -> str.charAt(i) == str.charAt(str.length() - 1 - i)) checks that every index's character matches its mirrored counterpart from the end.
  3. 3allMatch() returns true only if every single pair matches, and short-circuits on the first mismatch.
For "madam", the range covers indices 0 and 1; both mirrored pairs ('m','m') and ('a','a') match, so allMatch() returns true.
💡

Key Point: Like noneMatch() in the prime check, allMatch() stops at the first failing pair — a mismatched string doesn't pay for the full comparison.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: allMatch() checks each mirrored pair directly against the original string and stops at the first mismatch, without allocating a reversed copy.

Key Concepts

StreamIntStream.range()allMatch()

Interview Questions

How do you check a palindrome while ignoring case and spaces?

Normalise the text first: s.replaceAll("[^A-Za-z0-9]", "").toLowerCase() removes spaces and punctuation and lower-cases the rest. "A man, a plan, a canal: Panama" becomes amanaplanacanalpanama, which reads the same both ways.

Which approach is the most efficient?

The two-pointer comparison. It checks characters from both ends moving inward, stops at the first mismatch, and needs no extra memory. Reversing the whole string always builds a full copy, even when the first and last characters already differ.

Is an empty string a palindrome?

Yes. It reads the same forwards and backwards, and so does any single character — a correct palindrome check should return true for both, which makes them good edge cases to test.

Learn the Concept

Related Programs