Attempt at the Most dynamic FizzBuzz possible in Java

2018-03-09 08:41:27

I was trying to come up with the most dynamic fizzbuzz answer I could.. and well, this is what I came up with:

public static void main(String[] args) {

ultraFizzBuzz((Integer arg) -> {

String retVal = "";

if(arg % 3 == 0) { retVal += "fizz"; }

if(arg % 5 == 0) { retVal += "buzz"; }

return retVal;

});

}

public static void ultraFizzBuzz(modConditions tester) {

for(int i = 1; i < 100; i++) {

String result = tester.test(i);

if(result != "")

System.out.println(tester.test(i));

else

System.out.println(i);

}

}

In here the modConditions is an interface with a method (test) that returns type String.

What I was basically trying to do is create a super dynamic function that lets you add as many fizzes and buzzes and pops as you wanted.. but I think in the process accidentally made it so you end up writing 90% of the code in a lambda statement everytime you want to call it.

  • This is suboptimal, and kind of buggy:

    String result = tester.test(i);

    if(result != "")

    System.out.println(tester.test(i));

    else

    System.out.println(i);

    First of all, you are calling test.test(i) again, unnecessarily, instead of using result.

    Second, result != "" is not a good way to test for string equality. You're relying on the fact that the "" in ultraFizzBuzz() and the "" in the lambda happen to be the same exact object, due to the constant pool. If the lambda had been written with String retVal = new String(new char[] {}); instead, then the comparison would break. You should test for either "".equals(result) or result.isEmpty().

    You should never omit the "optional" braces, as you will be contributing to a future coding accident.

    Here's one better way to write the loop body:

    String result = tester.test(i);

    System.out.println("".equals(result) ? String.valueOf(i) : result);

    I'd expect a method that is named test() to return a boolean. It's surprising that

    2018-03-09 09:13:21
  • The most important problem I have with your code is, that it totally fails to achieve the goal you set yourself. This is not dynamic at all. Basically, you take the "normal" method body and put it into a lambda, but this lambda now is a complex function, which contains all of the business logic.

    Dynamically, you'd need a collection (probably list for being ordered) of lambdas, which each check a single input value and return an appropriate string representation (i.e. "fizz" or "buzz" or "whatever" or the empty string) and a method to apply this complete list on a single input, accumulate the results and perform the final check whether to output that string or the integer itself.

    Thus, start out with something like:

    Function fizz = i -> i % 3 == 0 ? "fizz" : "";

    Function buzz = i -> i % 5 == 0 ? "buzz" : "";

    Function barz = i -> i % 7 == 0 ? "barz" : "";

    List> fizzBuzzList = Arrays.asList(fizz, buzz, barz)

    2018-03-09 09:16:03