Check Palindrome String in Java
Problem
A palindrome is a string that reads the same forwards and backwards.
Given a string, determine whether it is a palindrome.
Java Program
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
Core Logic
The simplest check is to reverse the string and see if it matches the original — StringBuilder makes that a one-liner.
- 1The original string is passed to
new StringBuilder(str), which wraps it in a mutable buffer. - 2
.reverse()flips the character order in place, and.toString()converts the buffer back into a String. - 3
str.equals(reversed)compares the two strings character by character, not by reference. - 4If every character matches its mirrored position,
equals()returnstrueand the string is confirmed a palindrome.
"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.
Why: Reversing the string builds a second full copy of it, and equals() then compares both copies character by character.
Key Concepts
Approach 2: Manual Two-Pointer Comparison
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
Core Logic
No built-in reverse this time — just two pointers closing in from opposite ends, comparing characters as they go.
- 1Two index variables,
leftandright, start at the first and last character positions. - 2On each iteration,
charAt(left)andcharAt(right)are compared — if they differ, the string cannot be a palindrome, soisPalindromeis set tofalseand the loop exits early withbreak. - 3If the characters match,
leftmoves inward andrightmoves inward, narrowing the comparison window. - 4The loop stops once
leftmeets or crossesright, meaning every pair has been checked.
"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.
Why: The two pointers move inward comparing characters directly on the original string, without ever building a reversed copy.
Key Concepts
Approach 3: Recursive Check
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
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.
- 1The base case
if (left >= right) return true;fires once the pointers meet or cross, meaning every pair has matched. - 2Each call compares
str.charAt(left)andstr.charAt(right)— a mismatch immediately returnsfalse, short-circuiting the recursion. - 3If the characters match, the call recurses inward with
isPalindrome(str, left + 1, right - 1). - 4The recursion naturally stops as soon as either a mismatch is found or the pointers meet.
"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.
Why: Each call compares one pair and recurses inward, so up to n/2 stack frames stay alive at the deepest point.
Key Concepts
Approach 4: Java 8
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
Core Logic
The two-pointer comparison can be expressed as a single stream query — every mirrored pair of characters has to match.
- 1
IntStream.range(0, str.length() / 2)generates indices for just the first half of the string, since each comparison covers a mirrored pair. - 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
allMatch()returnstrueonly if every single pair matches, and short-circuits on the first mismatch.
"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.
Why: allMatch() checks each mirrored pair directly against the original string and stops at the first mismatch, without allocating a reversed copy.
Key Concepts
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.