Print Armstrong Numbers in a Range in Java
Problem
An Armstrong number is a number equal to the sum of its own digits, each raised to the power of the total digit count — printing them in a range means checking every candidate one by one.
Given a range of numbers, print every Armstrong number it contains.
Java Program
public class ArmstrongRange {
static boolean isArmstrong(int num) {
int digitCount = String.valueOf(num).length();
int original = num;
int sum = 0;
while (num > 0) {
int digit = num % 10;
sum += (int) Math.pow(digit, digitCount); // raise this digit to the power of the digit count
num /= 10;
}
return sum == original;
}
public static void main(String[] args) {
StringBuilder result = new StringBuilder();
for (int i = 1; i <= 1000; i++) {
if (isArmstrong(i)) { // reuse the single-number check for every candidate
if (result.length() > 0) result.append(", ");
result.append(i);
}
}
System.out.println("Armstrong numbers: " + result);
}
}Output
Core Logic
Testing every number in the range with the same digit-power-sum check used to test a single number finds every Armstrong number at once.
- 1
isArmstrong(n)is the single-number check, pulled out into its own method so it can be reused for every candidate. - 2The main loop tries every number from
1to1000, callingisArmstrong()on each. - 3A number that passes the check is appended to the result, separated by commas.
- 4Every single-digit number from 1 to 9 automatically qualifies, since any single digit raised to the power of 1 is itself.
Key Point: Reusing isArmstrong() as a standalone method avoids duplicating the digit-power-sum logic between the single-number checker and this range scanner.
Why: Every one of the n candidates in the range gets its own O(d) digit check, where d is that number's digit count.
Key Concepts
Approach 2: Java 8
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ArmstrongRangeStream {
static boolean isArmstrong(int num) {
int digitCount = String.valueOf(num).length();
int sum = String.valueOf(num).chars()
.map(c -> (int) Math.pow(c - '0', digitCount))
.sum();
return sum == num;
}
public static void main(String[] args) {
// Keeps only the numbers that pass the Armstrong check, then joins them
String result = IntStream.rangeClosed(1, 1000)
.filter(ArmstrongRangeStream::isArmstrong)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", "));
System.out.println("Armstrong numbers: " + result);
}
}
Output
Core Logic
The same range scan can filter a stream of candidate numbers down to just the Armstrong ones, then join the survivors.
- 1
IntStream.rangeClosed(1, 1000)generates every candidate number in the range. - 2
.filter(ArmstrongRangeStream::isArmstrong)keeps only the numbers that pass the Armstrong check, reusing the same helper method as a method reference. - 3
.mapToObj(String::valueOf)converts each surviving number into aString. - 4
.collect(Collectors.joining(", "))joins them into the final comma-separated result.
Key Point: Passing ArmstrongRangeStream::isArmstrong as a method reference to filter() is what lets the exact same check be reused without rewriting it as a lambda.
Why: The stream still checks every candidate's digits, and Collectors.joining() builds a result string holding every Armstrong number found.