eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

As we know, a number is a palindrome if it remains the same when its digits are reversed.

In this tutorial, we’ll explore different ways to check if a number is a palindrome, including iterative methods, recursive methods, and a few optimized ways to achieve our goal.

2. Problem Statement

Given a positive integer N, we want to find whether it’s a palindrome.

Input: N = 12321
Output: Yes
Explanation: 12321 is a palindrome number because after reversing its digits, it becomes 12321, the same as the original number.

Input: N = 123
Output: No
Explanation: 123 isn’t a palindrome number because after reversing its digits, the number becomes 321 which is different from the original number.

Now, let’s move into the approaches that help us find if a number is a palindrome.

3. Using Iterative Approach

The most straightforward way to check if a number is a palindrome is by reversing the digits and comparing the reversed number with the original one:

public static boolean isPalindromeIterative(int number) {
    int originalNumber = number;
    int reversedNumber = 0;

    while (number > 0) {
        int digit = number % 10;
	reversedNumber = reversedNumber * 10 + digit;
	number /= 10;
    }
    return originalNumber == reversedNumber;
}

So, we start by keeping a copy of the original number. This is important because we’ll need to compare it later. Next, we reverse the number by extracting its digits one by one. We do this by taking the number’s last digit and adding it to a new number we’re building, which starts at 0. Pulling each digit off the original number, we shrink it by dividing it by 10.

Let’s see the test case for the iterative approach:

@Test
void givenNumber_whenUsingIterativeApproach_thenCheckPalindrome() {     
    assertTrue(PalindromeNumber.isPalindromeIterative(12321));
    assertFalse(PalindromeNumber.isPalindromeIterative(123));
}

Once we’ve processed all the digits, we have a reversed version of the original number. The final step is to compare this reversed number with the original one we saved earlier. If they match, it means the number is a palindrome.

Let’s understand this logic:

  • Step 1: Set originalNumber = 12321 and reversedNumber = 0.
  • Step 2: Reverse the number
    • First digit: Extract 1, update the reversed number to 1, and reduce the number to 1232.
    • Second digit: Extract 2, update the reversedNumber to 12, and reduce the number to 123.
    • Third digit: Extract 3, update the reversedNumber to 123, and reduce the number to 12.
    • Fourth digit: Extract 2, update reversedNumber to 1232, and reduce the number to 1.
    • Fifth digit: Extract 1, update the reversedNumber to 12321, and reduce the number to 0.
  • Step 3: Since, reversedNumber (12321) matches the originalNumber (12321), so the number is a palindrome.

The loop runs once for each digit in the number. If the number has n digits, the time complexity is O(n). Each operation inside the loop (modulus, division, and multiplication) takes constant time O(1). So, the overall time complexity is O(n). And, we have used a constant amount of extra space for variables like originalNumber, reversedNumber, and digit, so the space complexity is O(1).

4. Using String Conversion

Another approach is to convert the number to a string, reverse it, and compare it with the original string:

public static boolean isPalindromeString(int number) {
    String original = String.valueOf(number);
    String reversed = new StringBuilder(original).reverse().toString();
    return original.equals(reversed);
}

In this approach, we first convert the number into a string. Then, we use a handy tool called StringBuilder to reverse that string. Once we have the reversed version, we compare it to the original string. If they match, the number is a palindrome.

Let’s see the test case for the string approach:

@Test
void givenNumber_whenUsingStringApproach_thenCheckPalindrome() {
    assertTrue(PalindromeNumber.isPalindromeString(12321));
    assertFalse(PalindromeNumber.isPalindromeString(123));
}

Let’s have a dry run of this code:

  • Step 1: Convert the number to String: original = “12321”.
  • Step 2: Reverse the string using the built-in method: reversed = “12321”.
  • Final step: Compare using original.equals(reversed). Since it returns true, it indicates that the number is a palindrome.

The loop in this approach iterates once for each digit in the number, leading to a time complexity of O(n), where n is the number of digits. Each operation within the loop, such as modulus, division, and multiplication, is performed in constant time, O(1). As for space complexity, only a constant amount of extra space is required for variables like originalNumber, reversedNumber, and digit, resulting in a space complexity of O(1).

5. Using Recursive Approach

We can also check for a palindrome using recursion, though it’s more complex and not as commonly used:

public static boolean isPalindromeRecursive(int number) {
    return isPalindromeHelper(number, 0) == number;
}

private static int isPalindromeHelper(int number, int reversedNumber) {
    if (number == 0) {
        return reversedNumber;
    }
    reversedNumber = reversedNumber * 10 + number % 10;
    return isPalindromeHelper(number / 10, reversedNumber);
}

In the recursive approach, we keep a copy of the original number. This is important because we’ll need to compare it later. Next, we reverse the number by extracting its digits one by one. We do this by taking the number’s last digit and adding it to a new number we’re building, which starts at zero. Pulling each digit off the original number, we shrink it by dividing it by 10.

Below is the test case for the recursive approach:

@Test
void givenNumber_whenUsingRecursiveApproach_thenCheckPalindrome() {
    assertTrue(PalindromeNumber.isPalindromeRecursive(12321));
    assertFalse(PalindromeNumber.isPalindromeRecursive(123));
}

Once we’ve processed all the digits, we have a reversed version of the original number. The final step is to compare this reversed number with the original one we saved earlier. If they match, it means the number is a palindrome.

Let’s dry-run this code to check if 12321 is a palindrome.

  • Step 1: Call isPalindromeHelper(12321, 0).
  • Step 2: Build reversed number recursively
    • First call: Reverse the last digit 1, update reversedNumber to 1, and call isPalindromeHelper(1232, 1).
    • Second call: Reverse 2, update reversedNumber to 12, and call isPalindromeHelper(123, 12)
    • Third call: Reverse 3, update reversedNumber to 123, and call isPalindromeHelper(12, 123).
    • Fourth call: Reverse 2, update reversedNumber to 1232, and call isPalindromeHelper(1, 1232).
    • Fifth call: Reverse 1, update reversedNumber to 12321, and call isPalindromeHelper(0, 12321).
  • Base case: Return reversedNumber (12321) and compare it with the originalNumber (12321). Since they match, it confirms that the number is a palindrome.

The recursive function is called once for each digit in the number, so the time complexity is O(n). Each recursive call involves a constant-time operation O(1). The recursion depth is equal to the number of digits in the number, so the space complexity is O(n) due to the call stack.

6. Half-Reversal Approach

This approach is more space-efficient than the full reversal method because it only reverses half of the number. The idea is to reverse the digits of the second half of the number and compare it with the first half.

Let’s understand this approach step by step along with its implementation and an example:

public static boolean isPalindromeHalfReversal(int number) {
    if (number < 0 || (number % 10 == 0 && number != 0)) {
        return false;
    }
    int reversedNumber = 0;
    while (number > reversedNumber) {
        reversedNumber = reversedNumber * 10 + number % 10;
        number /= 10;
    }
    return number == reversedNumber || number == reversedNumber / 10;
}

Here is the test case for the half-reversal approach:

@Test
void givenNumber_whenUsingHalfReversalApproach_thenCheckPalindrome() {
    assertTrue(PalindromeNumber.isPalindromeHalfReversal(12321));
    assertFalse(PalindromeNumber.isPalindromeHalfReversal(123));
}

Let’s dry-run this code to check if 12321 is a palindrome:

  • Initially, number = 12321 and reversedNumber = 0.
  • First iteration: number = 1232, reversedNumber = 1.
  • Second iteration: number = 123, reversedNumber = 12.
  • Third iteration: number = 12, reversedNumber = 123.
  • The loop stops because the number (12) is no longer greater than reversedNumber (123).
  • Since number == reversedNumber / 10, the function returns true.

Since we only process half of the digits, the time complexity is O(n), where n is the number of digits and we only use a few integer variables, so the space complexity is O(1).

7. Digit-by-Digit Comparison

This approach avoids reversing the number altogether by comparing digits from the start and end of the number moving toward the center.

Let’s understand this approach step by step along with its implementation and an example:

public static boolean isPalindromeDigitByDigit(int number) {
    if (number < 0) {
        return false;
    }
    int divisor = 1;
    while (number / divisor >= 10) {
        divisor *= 10;
    }
    while (number != 0) {
        int leading = number / divisor;
        int trailing = number % 10;
        if (leading != trailing) {
            return false;
        }
        number = (number % divisor) / 10;
        divisor /= 100;
    }
    return true;
}

Here’s the test case for this approach:

@Test
void givenNumber_whenUsingDigitByDigitApproach_thenCheckPalindrome() {
    assertTrue(PalindromeNumber.isPalindromeDigitByDigit(12321));
    assertFalse(PalindromeNumber.isPalindromeDigitByDigit(123));
}

Let’s run this code for 12321:

  • For 12321, initially, divisor = 10000, which is 10^(number of digits – 1).
  • Compare the first digit (1) with the last digit (1).
  • Remove both digits, adjust the divisor, and continue comparing.
  • If all digit pairs match, return true.

Since we compare digits from both ends moving towards the center, the time complexity is O(n), where n is the number of digits and we only use a few integer variables, so space complexity remains O(1).

8. Conclusion

In this article, we came across several approaches to check whether a number is palindrome. Choosing the right approach depends on our specific needs. If we’re looking for simplicity and can afford a bit more memory usage, the string conversion method might be our go-to. The half-reversal or digit-by-digit comparison methods offer excellent performance with minimal space overhead for a more efficient solution, especially with large numbers.

Each method has its charm, and understanding these different strategies can help us choose the most appropriate one for our situation, whether we prioritize readability, memory usage, or computational efficiency.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)