FizzBuzz Solution in Java 8

FizzBuzz is one of the most famous programming question from interviews, which is generally used to weed out programmers who can't program. The problem is deceptively simple but you can't solve it if you don't know how to build programming logic. I love it just for its simplicity. Now coming back to second part of this article, Java 8. Its been more than a year, I think it was March 18 last year when Java 8 was first released and till date the most common question I have got is, how to learn new features of Java 8? e.g. Optional, lambda expression or Stream. I think best way to learn Java 8 new features is the same as best way to learn any new programming language i.e. solving common coding problem, implementing data structure, common algorithms and implementing famous design patterns. I particularly find solving coding problem and excellent way to learn and master Java 8 Streams. If you can solve problems like Fibonacci series and couple of others using lambda expression and streams, you will progress quickly. Remember, Stream is a new way to write code without using for loop. Now coming back to our FizzBuzz problem, here is the problem statement and you need to solve it using Java 8.

Problem : For a given natural number greater than zero return:
    “Fizz” if the number is dividable by 3
    “Buzz” if the number is dividable by 5
    “FizzBuzz” if the number is dividable by 15
    the same number if number is neither divisible by 3 nor 5.

Bonus points if you write unit tests to check your solution, you must do even if not asked during Interviews.



Solving FizzBuzz in Java 8

Here is the complete solution of classic FizzBuzz problem using new features of Java 8. There are three methods in this program, first solution is the simplest way to solve FizzBuzz in Java without using any of Java 8 new feature, but second and third solution uses Java 8 features like lambda expressionOptional and map() function and new way of writing code.  First solution is self explanatory, we are checking if number is divisible by 15, which means it divisible by both 3 and 5, if yes we return FizzBuzz, otherwise we check for divisibility by 3 and 5, if its not divisible by any then we return the same number as String.

Second solution is interesting because its written in Java 8. Optional is a new concept and class introduced in Java 8, mainly to deal with null in better way and writing more expressive code which ensures that coder don't forget to check result of a method if its Optional. For the purpose of this program, we are using Optional as Stream, as you can treat it as Stream of either 1 or 0 element. If Optional contains value then it has one element otherwise it has zero element. The map() function is written using lambda expression, it goes to each element of  Optional and check if it is divisible by 3, 5 or both and accordingly return "Fizz", "Buzz" or "FizzBuzz". Let's understand this solution in little more detail :

public static String fizzBuzzInJava8(int number) {
        String result = Optional.of(number)
                .map(n -> (n % 3 == 0 ? "Fizz" : "") + (n % 5 == 0 ? "Buzz" : ""))
                .get();
        return result.isEmpty() ? Integer.toString(number) : result;
  }

 - First line is creating Optional from the number we passed.
 - Second line is actually equivalent of following code

public String map(int number){
   return  (n % 3 == 0 ? "Fizz" : "") + (n % 5 == 0 ? "Buzz" : "");
}

map is usually used to convert one type to another, also known as transformation. You can now see the logic of checking divisibility by 3 and 5 and how it produces "FizzBuzz" if number is divisible by both 3 and 5. If number is not divisible by neither 3 or 5 then this method will return an empty String.
FizzBuzz Solution in Java 8 using Streams

- Third line is call to get() method which returns value if Optional contains any value otherwise it throw NoSuchElementException, Since we know that after map() method, Optional will either contain "Fizz", "Buzz", "FizzBuzz" or empty String, we are safe to call get() method here.

- Last line in method simply check if result is empty then it return original number as String otherwise result itself.

Our second method is also applying same logic but its little bit more expressive for Java programmer who are just started learning this new way of coding. In this method, map method has exact the same logic as our first method, but you see we have reduce lot of boiler plate code related to method declaration using lambda expression.

import java.util.Optional;

/**
 * FizzBuzz problem solution in Java 8. It's a classical problem to filter
 * programmers who can't program. Now you can use this to check whether your
 * Java candidate knows programming with Java 8 Streams or not.
 *
 * Problem : Write a method in Java which will return "Fizz" if the number is
 * dividable by 3 "Buzz" if the number is dividable by 5 "FizzBuzz" if the
 * number is dividable by 15 the same number if no other requirement is
 * fulfilled.
 *
 * @author Javin Paul
 */
public class FizzBuzzJava8 {

    public static void main(String args[]) {
        System.out.println("FizzBuzz using simple Java : " + fizzBuzz(3));
        System.out.println("FizzBuzz solution using Java 8  : " + fizzBuzzInJava8(15));
    }

    /**
     * Simple Java solution of FizzBuzz Problem
     *
     * @param number
     * @return Fizz if number divisible by 3, Buzz if number divisible by 5
     * FizzBuzz if divisible by both 3 and 5, or else the same number
     */
    public static String fizzBuzz(int number) {
        if (number % 15 == 0) {
            return "FizzBuzz";
        } else if (number % 3 == 0) {
            return "Fizz";
        } else if (number % 5 == 0) {
            return "Buzz";
        }
        return Integer.toString(number);
    }

    /**
     * FizzBuzz Solution using Java 8 Optional, map and Stream map() function is
     * really useful here.
     *
     * @param number
     * @return Fizz, Buzz, FizzBuzz or the number itself
     */
    public static String fizzBuzzInJava8(int number) {
        String result = Optional.of(number)
                .map(n -> (n % 3 == 0 ? "Fizz" : "") + (n % 5 == 0 ? "Buzz" : ""))
                .get();
        return result.isEmpty() ? Integer.toString(number) : result;
    }

    /*
     * Another Java 8 solution, this time its little bit more expressive
     * for Java 8 newbie.
     */
    public static String fizzBuzzSolutionJava8(int input) {
        return Optional.of(input)
                .map(i -> {
                    if (i % (3 * 5) == 0) {
                        return "FizzBuzz";
                    } else if (i % 3 == 0) {
                        return "Fizz";
                    } else if (i % 5 == 0) {
                        return "Buzz";
                    } else {
                        return Integer.toString(i);
                    }
                }).get();
    }

}



JUnit Test for FizzBuzz problem

Here is our set of JUnit tests to check all three solution of Java 8. You can see we have in total 4 test cases, first to test with numbers which are only divisible by 3, second to test with number which are divisible by 5, third to test with numbers which are divisible by both 3 and 5 e.g. 15, 30 or 45 and last one with numbers which are not divisible by either 3 or 5 e.g. 1 or 2. Together these four method cover all the requirement of FizzBuzz problem.

import org.junit.Assert;
import org.junit.Test;

/**
 * JUnit tests for our three FizzBuzz solution, including two in Java 8. 
 * @author WINDOWS 8
 */
public class FizzBuzzJava8Test {

    @Test
    public void testWithNumberIsDividableBy3() {
        Assert.assertEquals("Fizz", FizzBuzzJava8.fizzBuzz(3));
        Assert.assertEquals("Fizz", FizzBuzzJava8.fizzBuzzInJava8(3));
        Assert.assertEquals("Fizz", FizzBuzzJava8.fizzBuzzSolutionJava8(3));
    }

    @Test
    public void testWithNumberIsDividableBy5() {
        Assert.assertEquals("Buzz", FizzBuzzJava8.fizzBuzz(5));
        Assert.assertEquals("Buzz", FizzBuzzJava8.fizzBuzzInJava8(5));
        Assert.assertEquals("Buzz", FizzBuzzJava8.fizzBuzzSolutionJava8(5));
    }

    @Test
    public void testWithNumberIsDividableBy15() {
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzz(15));
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzzInJava8(15));
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzzSolutionJava8(15));
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzz(45));
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzzInJava8(45));
        Assert.assertEquals("FizzBuzz", FizzBuzzJava8.fizzBuzzSolutionJava8(45));
    }

    @Test
    public void testOtherNumbers() {
        Assert.assertEquals("1", FizzBuzzJava8.fizzBuzz(1));
        Assert.assertEquals("1", FizzBuzzJava8.fizzBuzzInJava8(1));
        Assert.assertEquals("1", FizzBuzzJava8.fizzBuzzSolutionJava8(1));
        Assert.assertEquals("7", FizzBuzzJava8.fizzBuzz(7));
        Assert.assertEquals("7", FizzBuzzJava8.fizzBuzzInJava8(7));
        Assert.assertEquals("7", FizzBuzzJava8.fizzBuzzSolutionJava8(7));
    }
}

and here is the result of our JUnit test. You can see all four test cases have passed, which means all three solution are correct as per specification of fizzbuzz problem, don't you love the green bar?
How to solve FizzBuzz in Java 8 using lambda expression
This is the Netbeans's JUnit run window, you can see it clearly saying all 4 tests are passed within 62 milliseconds.


That's all about how to solve FizzBuzz in Java 8. As I said solving simple programming problems or doing code katas are great way to learn and master new features of Java 8, especially lambda expression and streams. FizzBuzz is one of the simplest of the problem but yet it teaches us how we can treat Optional as stream and use map function to transform each element of Optional. In the coming weeks we will also see some more examples of solving classic programming problems using Java 8 features. BTW,  If you are eager to do it by yourself, why not you try to solve these 20 String algorithm problems using Java 8 Streams, lambdas and other features.

If you like this tutorial and want to learn more about new features of Java 8, you will love to check out these amazing articles :
  • Top 20 Date and Time Examples of Java 8 (examples)
  • What is default method in Java 8. (tutorial)
  • Are you ready for Java 8 Certification? (read more)
  • How to use Map function in Java 8 (example)
  • 10 Examples of Stream API in Java (examples)
  • How to use Lambda Expression in Place of Anonymous class in Java 8 (solution)
  • 10 Java 7 Feature to revisit before you startswith Java 8 (list)
  • 10 Good Tutorials to Learn Java 8 (list)
  • How to Read File in Java 8 in one line? (example)
  • How to filter List in Java 8 using Predicates? (solution)
  • What is Effective final variable in Java 8? (answer)
  • Java 8 Comparator Example with Lambdas (example)
  • Java 8 tutorials and Books for FREE (resources)


4 comments :

Anonymous said...

Would be interesting to see the effects of object creation. I feel like the standard solution would be more efficient given a single input at a time

Anonymous said...

As a C/Java developer, I really hate java8 new features, beside the FuzzBuzz question is really easy(haven't heard too)!!! even my grandma would be accepted.
Java 8 new features were a really big disappointment.

Anonymous said...

That's a most stupid (mis)use of Optional I have ever seen.

TS said...

private static Func3 dividableMapping = (n, d, result) -> n % d == 0 ? result : "";
private static final List> FIZZ_BUZZ_FUNCTIONS = Arrays.asList(
n -> dividableMapping.call(n, 3, "Fizz"),
n -> dividableMapping.call(n, 5, "Buzz"));

public static String fizzBuzzInJava8(Integer n) {
String result = FIZZ_BUZZ_FUNCTIONS.stream().map(f -> f.call(n)).collect(Collectors.joining());
return result.isEmpty() ? String.valueOf(n) : result;
}

Post a Comment