Search code examples
lambdajava-8fizzbuzz

FizzBuzz using JDK8 Lambda


Just want to see by JDK8 lambda how small the program can be, my approach is using a result builder:

IntStream.rangeClosed(0 , 100).forEach(i ->{
        StringBuffer bfr= new StringBuffer();
        if(i % 3 == 0 )
            bfr.append("Fizz");
        if(i % 5 == 0 )
            bfr.append("Buzz");
        if(i % 3 != 0 && i % 5 != 0 )
            bfr.append(i);

        System.out.println(bfr.toString());
});

Can anyone try to use predicate instead ? I could not think of a way to do this.


Solution

  • Here are three solutions.

    Java 8 with Streams:

    IntStream.rangeClosed(0, 100).mapToObj(
            i -> i % 3 == 0 ?
                    (i % 5 == 0 ? "FizzBuzz" : "Fizz") :
                    (i % 5 == 0 ? "Buzz" : i))
            .forEach(System.out::println);
    

    Java 8 with Eclipse Collections:

    IntInterval.zeroTo(100).collect(
            i -> i % 3 == 0 ?
                    (i % 5 == 0 ? "FizzBuzz" : "Fizz") :
                    (i % 5 == 0 ? "Buzz" : i))
            .each(System.out::println);
    

    Java 8 with Eclipse Collections using Predicates:

    Interval.zeroTo(100).collect(
            new CaseFunction<Integer, String>(Object::toString)
                .addCase(i -> i % 15 == 0, e -> "FizzBuzz")
                .addCase(i -> i % 3 == 0, e -> "Fizz")
                .addCase(i -> i % 5 == 0, e -> "Buzz"))
            .each(System.out::println);
    

    Update:

    As of the Eclipse Collections 8.0 release, the functional interfaces in Eclipse Collections now extend the equivalent functional interfaces in Java 8. This means that CaseFunction can now be used as a java.util.function.Function, which means it will work with Stream.map(Function). The following example uses CaseFunction with a Stream<Integer>:

    IntStream.rangeClosed(0, 100).boxed().map(
            new CaseFunction<Integer, String>(Object::toString)
                    .addCase(i -> i % 15 == 0, e -> "FizzBuzz")
                    .addCase(i -> i % 3 == 0, e -> "Fizz")
                    .addCase(i -> i % 5 == 0, e -> "Buzz"))
            .forEach(System.out::println);
    

    Update:

    As of the Eclipse Collections 8.1 release, there is now support for primitive case functions. The code above can now be written as follows, removing the call to boxed. IntCaseFunction implements IntToObjectFunction which extends java.util.function.IntFunction.

    IntStream.rangeClosed(0, 100).mapToObj(
            new IntCaseFunction<>(Integer::toString)
                    .addCase(i -> i % 15 == 0, e -> "FizzBuzz")
                    .addCase(i -> i % 3 == 0, e -> "Fizz")
                    .addCase(i -> i % 5 == 0, e -> "Buzz"))
            .forEach(System.out::println);
    

    IntCaseFunction will also work with the IntInterval example, passed as the parameter to the collect method.

    Note: I am a committer for Eclipse Collections.