Introduction
Once you've learned how to check whether a single number is an Armstrong number, the next logical step is finding all Armstrong numbers within a given range. This is one of the most common follow-up questions in Java assignments and coding interviews because it tests whether you can reuse existing logic instead of rewriting it repeatedly.
Although the solution appears to be as simple as placing the Armstrong check inside a loop, a good implementation involves a few important design choices. Should the Armstrong check be extracted into a reusable method? Should the program print each Armstrong number immediately or store the results in a collection? What if you only need the total count rather than the numbers themselves?
In this guide, you'll learn the basic range-based solution, a reusable method approach, a counting-only variation, and a modern Java Streams implementation. You'll also discover why Armstrong numbers become surprisingly rare as the search range grows larger.
Quick Recap: What Is an Armstrong Number?
An Armstrong number (also called a narcissistic number) is a number whose digits, each raised to the power of the total number of digits, add up to the original number.
For example:
153
1³ + 5³ + 3³
=
1 + 125 + 27
=
153
Similarly,
1634
1⁴ + 6⁴ + 3⁴ + 4⁴
=
1634
The exponent must always equal the number of digits.
Method 1: Basic Range-Based Loop
The simplest approach checks every number in the range individually.
Java Program
public class ArmstrongRangeBasic {
public static void main(String[] args) {
int start = 1;
int end = 1000;
System.out.println("Armstrong numbers between " + start + " and " + end + ":");
for (int num = start; num <= end; num++) {
int digitCount = String.valueOf(num).length();
int sum = 0;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += (int) Math.pow(digit, digitCount);
temp /= 10;
}
if (sum == num) {
System.out.print(num + " ");
}
}
}
}
Output
Armstrong numbers between 1 and 1000:
1 2 3 4 5 6 7 8 9 153 370 371 407
How It Works
The outer loop iterates through every number between the starting and ending values.
For each number:
-
Count its digits.
-
Extract each digit.
-
Raise each digit to the digit count.
-
Add the powers together.
-
Compare the sum with the original number.
If both values match, the number is printed.
Although this solution works, the Armstrong-checking logic is embedded directly inside main(), making it difficult to reuse elsewhere.
Method 2: Using a Reusable isArmstrong() Method
A cleaner solution extracts the Armstrong logic into a separate method.
Java Program
public class ArmstrongRangeReusable {
static boolean isArmstrong(int num) {
int digitCount = String.valueOf(num).length();
int sum = 0;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += (int) Math.pow(digit, digitCount);
temp /= 10;
}
return sum == num;
}
public static void main(String[] args) {
int start = 1;
int end = 10000;
System.out.println("Armstrong numbers between " + start + " and " + end + ":");
for (int num = start; num <= end; num++) {
if (isArmstrong(num)) {
System.out.print(num + " ");
}
}
}
}
Output
Armstrong numbers between 1 and 10000:
1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
Why This Design Is Better
Separating the Armstrong logic from the range loop provides several advantages.
The isArmstrong() method can now be:
-
reused anywhere in the application
-
unit tested independently
-
called for printing
-
called for counting
-
called by Java Streams
without duplicating code.
Method 3: Counting Armstrong Numbers in a Range
Sometimes you only need the total number of Armstrong numbers rather than the actual list.
Java Program
public class ArmstrongRangeCount {
static boolean isArmstrong(int num) {
int digitCount = String.valueOf(num).length();
int sum = 0;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += (int) Math.pow(digit, digitCount);
temp /= 10;
}
return sum == num;
}
public static void main(String[] args) {
int start = 1;
int end = 100000;
int count = 0;
for (int num = start; num <= end; num++) {
if (isArmstrong(num)) {
count++;
}
}
System.out.println("Number of Armstrong numbers between "
+ start + " and " + end + ": " + count);
}
}
Output
Number of Armstrong numbers between 1 and 100000: 19
Instead of printing every Armstrong number, the program simply increments a counter whenever one is found.
This approach is ideal for:
-
statistics
-
validation
-
reporting
-
benchmarking
Method 4: Using Java Streams
Java Streams provide a concise, functional approach.
Java Program
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ArmstrongRangeStreams {
static boolean isArmstrong(int num) {
int digitCount = String.valueOf(num).length();
int sum = 0;
int temp = num;
while (temp != 0) {
int digit = temp % 10;
sum += (int) Math.pow(digit, digitCount);
temp /= 10;
}
return sum == num;
}
public static void main(String[] args) {
int start = 1;
int end = 10000;
List<Integer> armstrongNumbers = IntStream.rangeClosed(start, end)
.filter(ArmstrongRangeStreams::isArmstrong)
.boxed()
.collect(Collectors.toList());
System.out.println(armstrongNumbers);
}
}
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474]
How Streams Work
The pipeline executes in four stages:
-
Generate every number in the range.
IntStream.rangeClosed(start, end)
-
Keep only Armstrong numbers.
.filter(ArmstrongRangeStreams::isArmstrong)
-
Convert primitive
intvalues intoIntegerobjects.
.boxed()
-
Store everything inside a
List.
.collect(Collectors.toList())
Why Armstrong Numbers Become Rare
Armstrong numbers become increasingly uncommon as numbers grow larger.
For a number with d digits, the largest possible digit-power sum is:
d × 9ᵈ
For example:
For four-digit numbers,
4 × 9⁴
=
4 × 6561
=
26244
This comfortably covers every four-digit number.
However, as digit counts continue increasing, the total number of possible numbers grows much faster than the maximum achievable digit-power sum.
Consequently, the probability of finding another Armstrong number becomes extremely small.
An interesting mathematical fact:
There are exactly 88 Armstrong numbers in base 10, and the largest one contains 39 digits.
How Java Handles This Internally
Methods 1–3
Variables like:
-
num -
sum -
temp -
digitCount
are primitive values stored on the stack.
Each call to:
String.valueOf(num)
creates a temporary String object on the heap for digit counting.
Method 4
IntStream.rangeClosed() creates a stream pipeline.
Operations such as:
filter()
are lazy.
No filtering actually occurs until the terminal operation:
collect()
is executed.
The resulting List<Integer> is allocated on the heap, and each primitive int is automatically boxed into an Integer.
Real-Life Analogy
Imagine searching through millions of numbered lockers looking for a very unusual locker.
For each locker, you perform a calculation using only the digits printed on its own number.
Almost every locker fails.
Occasionally, however, one locker's number exactly equals the result of that calculation.
Those rare lockers are Armstrong numbers.
As the locker numbers become larger and larger, these special matches become increasingly difficult to find.
Comparison Table
| Method | Reusable | Output | Best Used When |
|---|---|---|---|
| Basic Loop | No | Printed directly | Small standalone programs |
| Reusable Method | Yes | Printed directly | Production-quality code |
| Counting Version | Yes | Count only | Statistics and validation |
| Java Streams | Yes | List | Functional programming style |
Best Practices
-
Always place the Armstrong logic inside a reusable
isArmstrong()method. -
Calculate the digit count only once for each number.
-
Print results directly unless they must be reused later.
-
Use Streams only when the project already favors functional programming.
-
Remember that Armstrong numbers become extremely rare for large ranges.
Common Mistakes
Duplicating Armstrong Logic
Avoid copying the same digit-processing code into multiple places.
Create one reusable method instead.
Assuming Armstrong Numbers Are Common
They are not.
Large ranges often contain very few Armstrong numbers.
Recalculating the Digit Count
Compute it once before processing the digits.
Collecting Results When Only a Count Is Needed
If only the number of Armstrong values matters, maintain a counter instead of building a list.
Incorrect Range Boundaries
Using:
num < end
instead of
num <= end
can accidentally skip a valid Armstrong number at the upper limit.
Expert Tips
A strong interview answer is:
"I would first extract the Armstrong logic into a reusable
isArmstrong()method. Then I'd iterate through the required range, calling that method for each number. Depending on the requirement, I could print the numbers, count them, or collect them into a list. The overall time complexity is O(n × d), where n is the number of values in the range and d is the average number of digits processed for each value."
Mentioning the reusable method and the time complexity demonstrates good software design as well as algorithmic understanding.
Pros and Cons
| Method | Advantages | Disadvantages |
|---|---|---|
| Basic Loop | Easy to understand | Logic cannot be reused |
| Reusable Method | Clean, modular, maintainable | Slightly more code |
| Counting Version | Uses very little memory | Doesn't store the actual numbers |
| Streams | Concise and modern | Slightly more overhead and less beginner-friendly |
Frequently Asked Questions
How do I print Armstrong numbers within a range in Java?
Loop through every number and call an isArmstrong() method for each one.
Why should I create a reusable isArmstrong() method?
It avoids duplicate code and allows the same logic to be reused for printing, counting, filtering, or testing.
How many Armstrong numbers exist?
There are 88 Armstrong numbers in base 10, and the largest one contains 39 digits.
Why do Armstrong numbers become rare?
As digit counts increase, the number of possible values grows much faster than the maximum achievable sum of powered digits.
Can I count Armstrong numbers without printing them?
Yes.
Increment a counter whenever isArmstrong() returns true.
Can Java Streams be used?
Yes.
Use:
IntStream.rangeClosed(start, end)
followed by:
filter()
and
collect()
to generate the list.
What is the time complexity?
O(n × d)
where:
-
n = numbers in the range
-
d = average number of digits
Is this a common interview question?
Yes.
It is a very common extension after implementing a single Armstrong-number check.
Can I search ranges larger than 100000?
Yes.
The same algorithm works for any range, although Armstrong numbers become increasingly sparse.
Should I print or store the results?
Print them for one-time output.
Store them in a list if additional processing is required later.
Does the reusable method work for single-digit numbers?
Yes.
Every single-digit number is an Armstrong number because:
digit¹ = digit
What is the largest Armstrong number?
The largest known Armstrong number in base 10 contains 39 digits, and mathematics proves that no larger Armstrong numbers exist.