Write Infinite FizzBuzz Sequence in Java 8


One way to write FizzBuzz program in Java 8 using Stream API.

Write a program that prints the integers from 1 to 100. But for multiples of three print “Fizz” instead of the number, and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

import java.util.function.IntPredicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class FizzBuzz {

    public static void main(String[] args) {
        IntStream numbers = IntStream.iterate(1, el -> el + 1);

        IntPredicate divBy3 = number -> number % 3 == 0;
        IntPredicate divBy5 = number -> number % 5 == 0;
        IntPredicate divBy3And5 = divBy3.and(divBy5);

        Stream<String> fizzBuzzStream = numbers
                .mapToObj(String::valueOf)
                .map(number -> parse(number, divBy3And5, () -> "FizzBuzz"))
                .map(number -> parse(number, divBy3, () -> "Fizz"))
                .map(number -> parse(number, divBy5, () -> "Buzz"));

        fizzBuzzStream.limit(30).forEach(System.out::println);
    }

    private static String parse(String numberStr, IntPredicate predicate, Supplier<String> supplier) {
        try {
            int number = Integer.parseInt(numberStr);
            if (predicate.test(number)) {
                return supplier.get();
            }
            return String.valueOf(number);
        } catch (NumberFormatException e) {
            return numberStr;
        }
    }
}

The above program will run into integer overflow. You can use BigInteger to overcome that as shown below.

import java.math.BigInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class FizzBuzzBigInteger {

    public static void main(String[] args) {
        BigInteger one = BigInteger.ONE;
        Stream<BigInteger> numbers = Stream.iterate(one, el -> el.add(one));

        Predicate<BigInteger> divBy3 = number -> number.remainder(BigInteger.valueOf(3)) == BigInteger.ZERO;
        Predicate<BigInteger> divBy5 = number -> number.remainder(BigInteger.valueOf(5)) == BigInteger.ZERO;
        Predicate<BigInteger> divBy3And5 = divBy3.and(divBy5);

        Stream<String> fizzBuzzStream = numbers
                .map(String::valueOf)
                .map(number -> parse(number, divBy3And5, () -> "FizzBuzz"))
                .map(number -> parse(number, divBy3, () -> "Fizz"))
                .map(number -> parse(number, divBy5, () -> "Buzz"));

        fizzBuzzStream.limit(100).forEach(System.out::println);
    }

    private static String parse(String numberStr, Predicate<BigInteger> predicate, Supplier<String> supplier) {
        try {
            BigInteger number = new BigInteger(numberStr);
            if (predicate.test(number)) {
                return supplier.get();
            }
            return numberStr;
        } catch (NumberFormatException e) {
            return numberStr;
        }
    }
}

The better and more functional approach suggested(in the comments) by Dominic is shown below.

import java.math.BigInteger;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class Fizzbuzz {

    public static void main(String[] args) {
        BigInteger one = BigInteger.ONE;

        Predicate<BigInteger> divBy3 = number -> Objects.equals(number.remainder(BigInteger.valueOf(3)), BigInteger.ZERO);
        Predicate<BigInteger> divBy5 = number -> Objects.equals(number.remainder(BigInteger.valueOf(5)), BigInteger.ZERO);
        Predicate<BigInteger> divBy3And5 = divBy3.and(divBy5);

        Stream<BigInteger> numbers = Stream.iterate(one, el -> el.add(one));

        Stream<String> fizzBuzzStream = numbers
                .map(FizzBuzzMatcher.matching(divBy3And5, () -> "FizzBuzz")
                        .otherwise(FizzBuzzMatcher.matching(divBy3, () -> "Fizz")
                                .otherwise(FizzBuzzMatcher.matching(divBy5, () -> "Buzz")
                                        .otherwise(BigInteger::toString))));

        fizzBuzzStream.limit(100).forEach(System.out::println);
    }
}

interface FizzBuzzMatcher extends Function<BigInteger, Optional<String>> {

    static FizzBuzzMatcher matching(Predicate<BigInteger> matcher, Supplier<String> resultMsgSupplier) {
        return number -> matcher.test(number) ? Optional.of(resultMsgSupplier.get()) : Optional.empty();
    }

    default Function<BigInteger, String> otherwise(Function<BigInteger, String> next) {
        return number -> apply(number).orElseGet(() -> next.apply(number));
    }
}

2 thoughts on “Write Infinite FizzBuzz Sequence in Java 8

  1. Dominic Fox

    I would prefer using Optional to indicate when a predicate doesn’t match the input – something like this:

    public final class InfiniteFizzBuzz {

    private InfiniteFizzBuzz() {
    }

    public interface FizzBuzzMatcher extends Function<BigInteger, Optional> {
    static FizzBuzzMatcher matching(Predicate matcher, String outputIfMatching) {
    return i -> matcher.test(i) ? Optional.of(outputIfMatching) : Optional.empty();
    }

    default Function otherwise(Function next) {
    return i -> apply(i).orElseGet(() -> next.apply(i));
    }
    }

    private static Predicate dividesBy(int divisor) {
    return i -> i.remainder(BigInteger.valueOf(divisor)).equals(BigInteger.ZERO);
    }

    private static final Predicate shouldFizz = dividesBy(3);
    private static final Predicate shouldBuzz = dividesBy(5);
    private static final Predicate shouldFizzBuzz = shouldFizz.and(shouldBuzz);

    public static final Stream fizzbuzzes =
    Stream.iterate(BigInteger.ONE, i -> i.add(BigInteger.ONE))
    .map(FizzBuzzMatcher.matching(shouldFizzBuzz, “FizzBuzz”)
    .otherwise(FizzBuzzMatcher.matching(shouldFizz, “Fizz”)
    .otherwise(FizzBuzzMatcher.matching(shouldBuzz, “Buzz”)
    .otherwise(BigInteger::toString))));

    public static void main(String[] args) {
    fizzbuzzes.limit(100).forEach(System.out::println);
    }
    }

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s