How to Check If a String Is Palindrome in Java

JavaJavaBeginner
Practice Now

Introduction

In this lab, you will learn how to check if a string is a palindrome in Java. We will explore different approaches, starting with the fundamental method of reversing a string and comparing it to the original.

Building upon this, you will then learn a more efficient technique using the two-pointer approach. Finally, we will enhance our palindrome check to ignore case and non-letter characters, making the check more robust.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java/BasicSyntaxGroup -.-> java/operators("Operators") java/BasicSyntaxGroup -.-> java/for_loop("For Loop") java/BasicSyntaxGroup -.-> java/while_loop("While Loop") java/StringManipulationGroup -.-> java/strings("Strings") java/SystemandDataProcessingGroup -.-> java/string_methods("String Methods") subgraph Lab Skills java/operators -.-> lab-559990{{"How to Check If a String Is Palindrome in Java"}} java/for_loop -.-> lab-559990{{"How to Check If a String Is Palindrome in Java"}} java/while_loop -.-> lab-559990{{"How to Check If a String Is Palindrome in Java"}} java/strings -.-> lab-559990{{"How to Check If a String Is Palindrome in Java"}} java/string_methods -.-> lab-559990{{"How to Check If a String Is Palindrome in Java"}} end

Reverse String and Compare

In this step, we will start by creating a simple Java program to reverse a string and then compare it with the original string. This is a fundamental step towards understanding string manipulation in Java and will serve as a building block for checking if a string is a palindrome.

First, let's create a new Java file. In the File Explorer on the left side of the WebIDE, right-click in the ~/project directory, select "New File", and name it StringReverse.java.

Now, open the StringReverse.java file in the editor and add the following code:

public class StringReverse {

    public static void main(String[] args) {
        String originalString = "hello";
        String reversedString = "";

        // Loop through the original string from end to beginning
        for (int i = originalString.length() - 1; i >= 0; i--) {
            // Append each character to the reversedString
            reversedString += originalString.charAt(i);
        }

        System.out.println("Original string: " + originalString);
        System.out.println("Reversed string: " + reversedString);

        // Compare the original and reversed strings
        if (originalString.equals(reversedString)) {
            System.out.println("The string is the same forwards and backwards.");
        } else {
            System.out.println("The string is NOT the same forwards and backwards.");
        }
    }
}

Let's break down this code:

  • String originalString = "hello";: We declare a String variable named originalString and assign it the value "hello".
  • String reversedString = "";: We declare an empty String variable named reversedString. We will build the reversed string here.
  • for (int i = originalString.length() - 1; i >= 0; i--): This is a for loop that starts from the last character of the originalString (index length() - 1) and goes down to the first character (index 0).
  • reversedString += originalString.charAt(i);: Inside the loop, originalString.charAt(i) gets the character at the current index i. We then append this character to the reversedString.
  • System.out.println(...): These lines print the original and reversed strings to the console.
  • if (originalString.equals(reversedString)): This if statement compares the originalString and reversedString using the equals() method. In Java, you should use equals() to compare the content of strings, not the == operator.
  • The if and else blocks print different messages based on whether the strings are the same.

Save the StringReverse.java file (Ctrl+S or Cmd+S).

Now, open the Terminal at the bottom of the WebIDE. Make sure you are in the ~/project directory. If not, type cd ~/project and press Enter.

Compile the Java code using the javac command:

javac StringReverse.java

If there are no errors, a StringReverse.class file will be created in the ~/project directory.

Finally, run the compiled Java program using the java command:

java StringReverse

You should see output similar to this:

Original string: hello
Reversed string: olleh
The string is NOT the same forwards and backwards.

In this case, "hello" is not the same forwards and backwards, so the program correctly identifies that.

Use Two-Pointer Approach for Palindrome

In the previous step, we reversed the entire string to check if it was a palindrome. While this works, it requires creating a new string, which can be inefficient for very long strings. A more efficient approach is to use the two-pointer technique.

The two-pointer technique involves using two pointers (variables that hold index positions) that start at different ends of the string and move towards the center. We compare the characters at these pointers. If they are always the same as the pointers move inwards, the string is a palindrome. If we find any mismatch, it's not a palindrome.

Let's create a new Java program to implement this. In the File Explorer on the left, create a new file named PalindromeChecker.java in the ~/project directory.

Open PalindromeChecker.java and add the following code:

public class PalindromeChecker {

    public static void main(String[] args) {
        String testString = "madam"; // Let's test with a palindrome
        boolean isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "racecar"; // Another palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "hello"; // Not a palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }
    }

    // Method to check if a string is a palindrome using two pointers
    public static boolean checkPalindrome(String str) {
        // Initialize two pointers
        int left = 0; // Pointer starting from the beginning
        int right = str.length() - 1; // Pointer starting from the end

        // Loop while the left pointer is less than the right pointer
        while (left < right) {
            // Compare characters at the left and right pointers
            if (str.charAt(left) != str.charAt(right)) {
                // If characters don't match, it's not a palindrome
                return false;
            }
            // Move the pointers inwards
            left++;
            right--;
        }

        // If the loop completes without finding any mismatch, it's a palindrome
        return true;
    }
}

Here's what's happening in the new code:

  • We've created a separate method called checkPalindrome that takes a String as input and returns a boolean (true if it's a palindrome, false otherwise). This makes our code more organized and reusable.
  • Inside checkPalindrome, we initialize left to 0 (the index of the first character) and right to str.length() - 1 (the index of the last character).
  • The while (left < right) loop continues as long as the left pointer is to the left of the right pointer.
  • if (str.charAt(left) != str.charAt(right)) compares the characters at the current left and right positions. If they are different, we immediately know it's not a palindrome and return false.
  • If the characters match, we move the pointers inwards: left++ increments the left pointer, and right-- decrements the right pointer.
  • If the loop finishes without returning false, it means all the compared characters matched, so the string is a palindrome, and we return true.
  • In the main method, we call checkPalindrome with different test strings and print the results.

Save the PalindromeChecker.java file.

Now, compile and run the program in the Terminal:

javac PalindromeChecker.java
java PalindromeChecker

You should see the following output:

"madam" is a palindrome.
"racecar" is a palindrome.
"hello" is not a palindrome.

This demonstrates how the two-pointer approach efficiently checks for palindromes without reversing the entire string.

Ignore Case and Non-Letters in Palindrome

In the previous step, our palindrome checker worked for simple strings like "madam" and "racecar". However, real-world palindromes often ignore capitalization and punctuation. For example, "A man, a plan, a canal: Panama" is considered a palindrome.

In this step, we will enhance our PalindromeChecker to handle these cases by ignoring non-letter characters and treating uppercase and lowercase letters the same.

Open the PalindromeChecker.java file in the WebIDE editor. We will modify the checkPalindrome method.

Replace the existing checkPalindrome method with the following updated version:

    // Method to check if a string is a palindrome using two pointers,
    // ignoring case and non-letter characters
    public static boolean checkPalindrome(String str) {
        // Initialize two pointers
        int left = 0; // Pointer starting from the beginning
        int right = str.length() - 1; // Pointer starting from the end

        // Loop while the left pointer is less than the right pointer
        while (left < right) {
            // Move left pointer past non-letter characters
            while (left < right && !Character.isLetter(str.charAt(left))) {
                left++;
            }

            // Move right pointer past non-letter characters
            while (left < right && !Character.isLetter(str.charAt(right))) {
                right--;
            }

            // If left and right pointers haven't crossed and characters don't match (ignoring case)
            if (left < right && Character.toLowerCase(str.charAt(left)) != Character.toLowerCase(str.charAt(right))) {
                // If characters don't match, it's not a palindrome
                return false;
            }

            // Move the pointers inwards
            left++;
            right--;
        }

        // If the loop completes without finding any mismatch, it's a palindrome
        return true;
    }

Here are the changes we made:

  • We added two while loops inside the main while (left < right) loop.
  • The first inner while loop (while (left < right && !Character.isLetter(str.charAt(left)))) moves the left pointer forward as long as it's still to the left of the right pointer and the character at the left pointer is not a letter (!Character.isLetter(...)).
  • The second inner while loop (while (left < right && !Character.isLetter(str.charAt(right)))) moves the right pointer backward as long as it's still to the left of the right pointer and the character at the right pointer is not a letter.
  • The comparison if (left < right && Character.toLowerCase(str.charAt(left)) != Character.toLowerCase(str.charAt(right))) now includes two important checks:
    • left < right: This ensures we only compare characters if the pointers haven't crossed after skipping non-letters.
    • Character.toLowerCase(...): This converts both characters to lowercase before comparing them, effectively ignoring case.
  • If the characters (after converting to lowercase) don't match, we return false.
  • If they match, we move both pointers inwards (left++, right--) to check the next pair of characters.

Now, let's modify the main method to test with a string that includes spaces, punctuation, and mixed case. Replace the existing test cases in the main method with this:

    public static void main(String[] args) {
        String testString = "A man, a plan, a canal: Panama"; // A classic palindrome
        boolean isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "No 'x' in Nixon"; // Another palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }

        testString = "hello world"; // Not a palindrome
        isPalindrome = checkPalindrome(testString);

        if (isPalindrome) {
            System.out.println("\"" + testString + "\" is a palindrome.");
        } else {
            System.out.println("\"" + testString + "\" is not a palindrome.");
        }
    }

Save the PalindromeChecker.java file.

Compile and run the updated program in the Terminal:

javac PalindromeChecker.java
java PalindromeChecker

You should now see the following output, correctly identifying the palindromes even with non-letter characters and mixed case:

"A man, a plan, a canal: Panama" is a palindrome.
"No 'x' in Nixon" is a palindrome.
"hello world" is not a palindrome.

You have successfully enhanced your palindrome checker to handle more complex strings!

Summary

In this lab, we learned how to check if a string is a palindrome in Java. We started by implementing a method to reverse a string and comparing it to the original string to determine if it's a palindrome. This involved creating a Java file, writing code to iterate through the string in reverse, and using the equals() method for comparison.

We then explored the two-pointer approach, a more efficient method for palindrome checking that avoids creating a new reversed string. Finally, we enhanced our palindrome check to ignore case and non-letter characters, making the check more robust for real-world scenarios.