简体   繁体   中英

Checking if the Given numger is an Armstrong number with Java 8 Streams

I'm having an issue while checking if the supplied number is Armstrong or not.

I'm passing the int value of 370 , but as a result I'm getting the value of 343 .

Can someone point out what I'm missing?

Input: 370 Expected: 370

static int isArmStrong(int num) {
    return IntStream.rangeClosed(1, num)
            .map(i -> i / 10)
            .map(i -> i % 10)
            .reduce(1, (a, b)-> (b * b * b));       
}

You have to iterate over the digits of the given number. But instead you've created a stream of numbers from 1 to the given number inclusive.

And you've hard-coded the power of 3 is (ie your solution is intended to deal only with 3-digit numbers).

Also, there's a bug in the reduce operation:

reduce(1,(a,b)-> (b*b*b))

What your method is actually returns is a cube of the last element in the stream, which for the input 370 happens to be a 7 . Because you are ignoring the argument a in the accumulator ( a - represents a sum accumulated so far and b - is a next element).

And it'll be better if isArmstrong method would return a boolean value. Because it's meant to perform a check as you've and by convention methods that start with is or has are expected to return a boolean .

To address this problem correctly, you need to follow the classical algorithm ( wiki ) iterating over the digits of the given number.

You can do it with streams by the iterate() operation. Its Java 8 flavor which take two arguments ( a seed and a unary operator that is used to generate the next element ) creates an infinite stream . You need to apply the limit() operation to trim the number of elements in the stream to the number of digits in the given number.

Apply map() to obtain the power of every element and then apply the terminal operation sum() to get the result.

public static boolean isArmstrong(int num) {
    return num == getArmstrongSum(num);
}

public static int getArmstrongSum(int num) {
    int pow = String.valueOf(num).length();
    return IntStream.iterate(num, i -> i / 10)
            .limit(pow)
            .map(i -> (int) Math.pow(i % 10, pow))
            .sum();
}

main()

public static void main(String[] args) {
    System.out.println(getArmstrongSum(370));
    System.out.println(isArmstrong(370));
}

Output

370
true

To generate the List of Armstrong number with java 8 stream.

static boolean isArmStrong(int num) {
    return num==armStrongViaStream(num);
}

//via Stream
static int armStrongViaStream(int num) {
    int size = String.valueOf(num).length();
    return IntStream.iterate(num, i->i/10)
            .limit(size)
            .map(i-> (int)Math.pow(i%10, size))
            .sum();
        }

//List via Stream
static List<Integer> armStrongListUpto(int num){
    List<Integer> list=new ArrayList<>();
    list=IntStream.rangeClosed(0, num)
            .filter(i->isArmStrong(i)).boxed()
            .collect(Collectors.toList());
return list;    
}

Main Method

System.out.println("List via Java Stream ->"+armStrongListUpto(500));

Output will return a list.

List via Java Stream ->[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407]

if we need to generate list of Armstrong number between a range in Java 8 Streams.

static List<Integer> armStrongBetweenNum(int start,int end){
    List<Integer> list=new ArrayList<>();
    list=IntStream.rangeClosed(start, end)
            .filter(i->isArmStrong(i)).boxed()
            .collect(Collectors.toList());
    return list;
}

Main function(call)

System.out.println("Armstrong num between given end points ->"+armStrongBetweenNum(1, 500));

output

Armstrong num between given end points ->[1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM