How to count the number of trailing zeroes in an integer using Java 8 Stream/Lambda?

让人想犯罪 __ 提交于 2019-12-23 22:57:56

问题


How to count the number of trailing zeroes in an integer using Java 8 Stream/Lambda?

Basically the logic should be: keep the integer dividing by 10 as long as the remainder is 0 (the quotient will be supplied to the next division) and count the occurrence(s).

e.g.

12300 % 10 == 0 true

1230 % 10 == 0 true

123 % 10 == 0 false

Answer: 2

Note: I prefer not to involve String here :-)


回答1:


If this is a purely hypothetical question, here is a purely hypothetical answer of how you can do it:

static int countZeroes(int value) {
    if(value == 0) // we need to handle this case explicitly
        return 1; 
    IntStream s = IntStream.iterate(value, v -> v / 10);
    return (int) takeWhile(s, v -> v > 0 && v % 10 == 0)
            .count();

}

It uses a helper function takeWhile that is available in Java 9 but not in Java 8 so has to be emulated like this:

// In Java 9 there is a standard takeWhile
// https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.html#takeWhile-java.util.function.Predicate-
// but in Java 8 I have to emulate it
static IntStream takeWhile(IntStream s, final IntPredicate pr) {
    final Spliterator.OfInt origSp = s.spliterator();

    Spliterator.OfInt filtered = new Spliterators.AbstractIntSpliterator(origSp.estimateSize(), 0) {
        boolean lastPredicate = true;

        @Override
        public boolean tryAdvance(final IntConsumer action) {
            if (!lastPredicate)
                return false;

            origSp.tryAdvance((int v) -> {
                lastPredicate = pr.test(v);
                if (lastPredicate) {
                    action.accept(v);
                }
            });
            return lastPredicate;
        }
    };

    return StreamSupport.intStream(filtered, false);
}

The idea is that

IntStream.iterate(value, v1 -> v1 / 10).takeWhile(v -> v > 0)

should generate a stream of cutting digits at the end one by one and then you can apply takeWhile(v -> v % 10 == 0).count() to count the number of zeros and finally you can merge those two takeWhiles into one.




回答2:


Considering you don't have Java9's takeWhile method, this can also do the trick:

static final int[] POWERS_OF_10 = { 1000000000, 100000000, 10000000,
        1000000, 100000, 10000, 1000, 100, 10 };

static int trailingZeros(int number) {
    return Arrays.stream(POWERS_OF_10)      // reversed stream of of 10^n
                 .map(pow -> number % pow)  // stream of rests
                 .reduce(0, (count, rest) -> (rest == 0) ? count + 1 : 0);
}



回答3:


Here's another way:-

private static int countTrailingZeroes(int n) {
    int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
    return IntStream.rangeClosed(0, length)
            .map(i -> length - i)           //reverse stream
            .map(o -> (int) Math.pow(10, o))
            .filter(o -> n % o == 0)
            .boxed()
            .findFirst()
            .map(i -> (int) Math.log10(i))  //number of digits minus 1
            .orElse(0);
}

@Holger's edit:

private static int countTrailingZeroes(int n) {
    int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
    return IntStream.rangeClosed(0, length)
            .map(i -> length - i)           //reverse stream
            .filter(o -> n % (int) Math.pow(10, o) == 0)
            .findFirst()
            .orElse(0);
}


来源:https://stackoverflow.com/questions/54426602/how-to-count-the-number-of-trailing-zeroes-in-an-integer-using-java-8-stream-lam

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!