A palindrome is a string or a number that reads the same forward and backward, such as level, racecar or 1221, and a palindrome program in Java checks it by comparing characters from both ends toward the middle. For numbers, we reverse the digits with % 10 and / 10 and compare the result with the original.
We write palindrome checks in interviews and in text-processing code, and the same two-pointer technique appears in bioinformatics, where some DNA sequences mirror themselves.
The following example checks words, a phrase and a number with the methods from section 1, section 3 and section 5.
boolean level = isPalindrome("level"); // true
boolean java = isPalindrome("java"); // false
boolean phrase = isPalindromePhrase("A man, a plan, a canal: Panama"); // true
boolean number = isPalindromeNumber(1221); // true
The phrase needs its own method, because the spaces, commas and capital letters would break a plain character comparison. We start with the string checks, move on to recursion, streams and numbers, and finish with a real-world use and a comparison of all the methods.
1. Palindrome Program in Java with Two Pointers
The two-pointer check compares the first character with the last, the second with the second-to-last, and so on. It stops at the first mismatch, and if the two indexes meet in the middle without a mismatch, the string is a palindrome.

static boolean isPalindrome(String s) {
if (s == null) {
return false;
}
for (int left = 0, right = s.length() - 1; left < right; left++, right--) {
if (s.charAt(left) != s.charAt(right)) {
return false; // first mismatch decides
}
}
return true;
}
boolean racecar = isPalindrome("racecar"); // true
boolean noon = isPalindrome("noon"); // true
boolean single = isPalindrome("x"); // true
boolean empty = isPalindrome(""); // true
boolean nothing = isPalindrome(null); // false
The two-pointer check needs at most n / 2 comparisons and no extra memory, which makes it the best default for strings. An empty string and a single character are palindromes by definition, whereas null is not a string at all, so the method returns false instead of throwing an exception.
2. Palindrome Check by Reversing the String
The shortest version reverses the string with StringBuilder, as described in our reverse a string article, and compares the copy with the original. The call equalsIgnoreCase() makes the check ignore upper and lower case.
String word = "Madam";
boolean exact = word.equals(new StringBuilder(word).reverse().toString()); // false
boolean ignoreCase = word.equalsIgnoreCase(new StringBuilder(word).reverse().toString()); // true
The reverse-and-compare version always builds a full copy, even when the first and the last character already differ. That is fine for short strings, but the two-pointer version from section 1 does less work.
A common beginner version builds the reverse with reverse = reverse + s.charAt(i) in a loop. Each + copies the whole string built so far, so that loop costs O(n2) and is the slowest way to check a palindrome.
3. Ignoring Case, Spaces and Punctuation
Phrases such as “Was it a car or a cat I saw?” are palindromes only when we skip spaces and punctuation and compare letters without case. The two-pointer loop moves each index past characters that are not letters or digits, using Character.isLetterOrDigit(), and compares the rest in lower case.
static boolean isPalindromePhrase(String s) {
if (s == null) {
return false;
}
int left = 0;
int right = s.length() - 1;
while (left < right) {
char l = s.charAt(left);
char r = s.charAt(right);
if (!Character.isLetterOrDigit(l)) {
left++;
} else if (!Character.isLetterOrDigit(r)) {
right--;
} else if (Character.toLowerCase(l) != Character.toLowerCase(r)) {
return false;
} else {
left++;
right--;
}
}
return true;
}
boolean car = isPalindromePhrase("Was it a car or a cat I saw?"); // true
boolean nixon = isPalindromePhrase("No 'x' in Nixon"); // true
boolean almost = isPalindromePhrase("Was it a car or a dog I saw?"); // false
A shorter alternative cleans the string first with a regex and runs the plain check. It reads well, but it creates a new string, and the pattern [^A-Za-z0-9] also removes letters such as é or ü, which isLetterOrDigit() keeps.
String cleaned = "Step on no pets!".replaceAll("[^A-Za-z0-9]", "").toLowerCase(); // "steponnopets"
boolean pets = isPalindrome(cleaned); // true
4. Recursive and Stream Versions
Interviewers sometimes ask for a recursive palindrome check. The recursive method compares the outer pair and calls itself for the inner part, and the base case is reached when the indexes meet. We pass indexes instead of calling substring(), so no characters are copied.
static boolean isPalindromeRecursive(String s, int left, int right) {
if (left >= right) {
return true; // base case
}
if (s.charAt(left) != s.charAt(right)) {
return false;
}
return isPalindromeRecursive(s, left + 1, right - 1);
}
String kayak = "kayak";
boolean recKayak = isPalindromeRecursive(kayak, 0, kayak.length() - 1); // true
String howto = "howtodoinjava";
boolean recHowto = isPalindromeRecursive(howto, 0, howto.length() - 1); // false
Each call adds a stack frame, so a very long string can cause a StackOverflowError, as our recursion tutorial explains. With streams, IntStream.range() runs over the first half of the indexes, and allMatch() stops at the first mismatch, like the loop.
String radar = "radar";
boolean streamRadar = IntStream.range(0, radar.length() / 2).allMatch(i -> radar.charAt(i) == radar.charAt(radar.length() - 1 - i)); // true
5. Palindrome Number Program in Java
A number is a palindrome when its digits read the same in both directions, such as 121 or 1221. We take the last digit with n % 10, append it to a reversed number with reversed * 10 + digit, and remove it with n / 10. Negative numbers are not palindromes, because -121 read backward is 121-.
A full reversal can overflow an int. For example, 1,999,999,999 is a valid int, but its reverse 9,999,999,991 is not. The safe version reverses only the second half of the digits and compares it with the first half, so the reversed value never gets larger than the original.
static boolean isPalindromeNumber(int n) {
if (n < 0 || (n % 10 == 0 && n != 0)) {
return false; // negatives and numbers ending in 0
}
int reversedHalf = 0;
while (n > reversedHalf) {
reversedHalf = reversedHalf * 10 + n % 10;
n /= 10;
}
return n == reversedHalf || n == reversedHalf / 10; // even or odd digit count
}
boolean even = isPalindromeNumber(1221); // true
boolean oddDigits = isPalindromeNumber(12321); // true
boolean negative = isPalindromeNumber(-121); // false
boolean tens = isPalindromeNumber(10); // false
boolean zero = isPalindromeNumber(0); // true
boolean maxInt = isPalindromeNumber(Integer.MAX_VALUE); // false
For 12321, the loop stops with n = 12 and reversedHalf = 123, so the middle digit 3 is dropped with reversedHalf / 10. A number that ends in 0 cannot be a palindrome unless it is 0, because no number starts with 0.
Some palindrome programs try to ignore underscores in large numbers. Underscores such as 1_00_00_001 exist only in Java source code since Java 7, and the compiler removes them, so the int value has no underscores to ignore.
int withUnderscores = 1_00_00_001; // 10000001
boolean underscoreCheck = isPalindromeNumber(withUnderscores); // true
boolean viaString = isPalindrome(String.valueOf(1_00_00_001)); // true
6. Palindromic Sites in DNA Sequences
In molecular biology, many restriction enzymes cut DNA at sites that read the same on both strands. The enzyme EcoRI recognizes GAATTC, and the complementary strand, read in its own direction, is also GAATTC. Software that scans a genome for such cutting sites runs the two-pointer check with one change, as it compares each base with the complement of its partner instead of the same base.
static boolean isReverseComplementPalindrome(String dna) {
for (int left = 0, right = dna.length() - 1; left <= right; left++, right--) {
char expected = switch (dna.charAt(left)) {
case 'A' -> 'T';
case 'T' -> 'A';
case 'G' -> 'C';
case 'C' -> 'G';
default -> throw new IllegalArgumentException("Not a DNA base: " + dna.charAt(left));
};
if (dna.charAt(right) != expected) {
return false;
}
}
return true;
}
boolean ecoRI = isReverseComplementPalindrome("GAATTC"); // true
boolean plain = isPalindrome("GAATTC"); // false
boolean other = isReverseComplementPalindrome("GATTTC"); // false
We can see that GAATTC is not a palindrome as plain text, yet it is the kind of palindrome that biologists care about. The loop runs to left <= right, because a middle base would have to be its own complement, which no DNA base is, so odd-length sequences are rejected.
7. Palindrome Methods Side by Side
All string checks run in O(n) time, but they differ in memory, in how early they stop and in what input they accept. The number check runs in O(d) time, where d is the number of digits.
| Method | Extra memory | Stops at first mismatch | Handles phrases | Notes |
|---|---|---|---|---|
| Two pointers | O(1) | Yes | No | Best default for strings |
| Two pointers with skipping | O(1) | Yes | Yes | Ignores case, spaces and punctuation |
| StringBuilder.reverse() and equals() | O(n) | No | No | Shortest code |
| Regex cleanup and check | O(n) | No | Yes, ASCII only | Drops accented letters |
| Recursion with indexes | O(n) stack | Yes | No | Interview exercise |
| IntStream.allMatch() | O(1) | Yes | No | Stream style |
| Half-digit reversal | O(1) | Yes | Not applicable | Numbers, no overflow |
All the string methods compare char values. For text with emoji or other characters outside the Basic Multilingual Plane, a check that compares s.codePoints().toArray() from both ends gives the correct answer.
8. Palindrome FAQs
Developers search for these questions and interviewers ask them about palindrome programs in Java.
8.1. How do we check a palindrome without reversing the string?
With the two-pointer loop from section 1. It compares characters from both ends, needs no copy of the string and returns at the first mismatch.
8.2. Is an empty string a palindrome?
Yes. An empty string reads the same in both directions, so all methods in this article return true for it, and the same holds for a single character.
8.3. Can a negative number be a palindrome?
No, under the usual definition. The minus sign is part of the number, and -121 read backward is 121-, which is not a number. If a task wants to ignore the sign, we pass Math.abs(n), except for Integer.MIN_VALUE, whose absolute value does not fit in an int.
8.4. Which palindrome check is the fastest?
The two-pointer check, because it reads at most half of the characters and allocates nothing. The StringBuilder version is fast enough for short strings, but it always copies the whole string.
8.5. How do we check a palindrome number by converting it to a String?
We call isPalindrome(String.valueOf(n)), as in the last example of section 5. It is short and correct for negative numbers too, because the minus sign never matches a digit, but it creates a string for each check.
9. Conclusion
A palindrome program in Java compares characters from both ends toward the middle and stops at the first mismatch, which needs no extra memory. For phrases, the same loop skips everything except letters and digits and compares in lower case.
For numbers, reversing only half of the digits avoids int overflow and handles negative numbers and trailing zeros. Reversing the whole string with StringBuilder is the shortest code, and the recursive and stream versions are useful for interviews, as long as we remember what each one costs.
10. References
- Character.isLetterOrDigit() (Java SE 25 API)
- StringBuilder.reverse() (Java SE 25 API)
- IntStream.allMatch() (Java SE 25 API)
- JLS 25, Integer Literals
Happy Learning !!
Hi Lokesh,
Can you please explain a program to find the longest substring palindrome.
class A
{
int v;
A()
{
calc();
}
public void calc()
{
System.out.println(“A class Method “);
}
}
class B extends A
{
B()
{
calc();
}
public void calc()
{
System.out.println(“B class Method “);
}
public static void main(String ar[])
{
A a1 = new B();
}
}
output
B class Method
B class Method
calc() method in A class is why not executed in A class Constuctor or why execute calc() method of B class
sir plz solve my problem
Because you have override the method. Any method called is always first looked upon class which instance is being created. If not found there, ONLY then super class is looked upon. In both constructor calls, calc() method is found in B so JVM does not go beyond that i.e. A is not looked into.
We can easily do this in java using StringBuilder /StringBuffer also.
StringBuilder str = new StringBuilder(“malayalam”);
System.out.println(“reverse = ” + str.reverse());
then compare original string and reversed one
Good example. You are right. We can use above method as well.
I have to say, the following code doesn’t seem written by someone with 8 Years of rich experience in java technology. Very bad code.
public static boolean checkIntegerPalindrome(int number) { boolean isPalindrome = false; if(number == reverse(number)) { isPalindrome = true; } return isPalindrome; }Please suggest the good way..
Andy, why won’t you just code:
public static boolean checkIntegerPalindrome(int number) {
return number == reverse number;
}
??
It should be reverse(number);
public static boolean checkIntegerPalindrome(int number)
{
return number == reverse(number);
}