kata

不久前,我使用Java 8流和lambda解决了FizzBu​​zz kata问题。 尽管最终结果是可行的,但中间步骤却没有。 我当然可以做得更好。

与往常一样,让我们​​从失败的测试开始:

package remonsinnema.blog.fizzbuzz;
+
+ import static org.junit.Assert.assertEquals;
+
+ import org.junit.Test;
+
+
+ public class WhenFunctionallyFuzzingAndBuzzing {
+
+   private final FizzBuzzer fizzBuzzer = new FizzBuzzer();
+
+   @Test
+   public void shouldReplaceMultiplesOfThreeWithFizzAndMultiplesOfFiveWithBuzz() {
+     assertEquals(“1”, “1”, fizzBuzzer.apply(1));
+   }
+
+ }
package remonsinnema.blog.fizzbuzz;
+
+ import java.util.function.Function;
+
+
+ public class FizzBuzzer implements Function<Integer, String> {
+
+   @Override
+   public String apply(Integer n) {
+     return null;
+   }
+
+ }

请注意,我马上就使用Java的Function开始了函数课程。

我伪造实现以使测试通过:

public class FizzBuzzer implements Function<Integer, String> {@Overridepublic String apply(Integer n) {
–     return null;
+     return “1”;}}

并重构测试以消除重复:

public class WhenFunctionallyFuzzingAndBuzzing {@Testpublic void shouldReplaceMultiplesOfThreeWithFizzAndMultiplesOfFiveWithBuzz() {
–     assertEquals(“1”, “1”, fizzBuzzer.apply(1));
+     assertFizzBuzz(“1”, 1);
+   }
+
+   private void assertFizzBuzz(String expected, int value) {
+     assertEquals(Integer.toString(value), expected, fizzBuzzer.apply(value));}}

然后,我添加另一个测试以概括实现:

public class WhenFunctionallyFuzzingAndBuzzing {@Testpublic void shouldReplaceMultiplesOfThreeWithFizzAndMultiplesOfFiveWithBuzz() {assertFizzBuzz(“1”, 1);
+     assertFizzBuzz(“2”, 2);}private void assertFizzBuzz(String expected, int value) {public class FizzBuzzer implements Function<Integer, String> {@Overridepublic String apply(Integer n) {
–     return “1”;
+     return Integer.toString(n);}}

好的,到目前为止非常标准的东西。 接下来,我需要将3替换为“ Fizz”:

public class WhenFunctionallyFuzzingAndBuzzing {public void shouldReplaceMultiplesOfThreeWithFizzAndMultiplesOfFiveWithBuzz() {assertFizzBuzz(“1”, 1);assertFizzBuzz(“2”, 2);
+     assertFizzBuzz(“Fizz”, 3);}nbsp;private void assertFizzBuzz(String expected, int value) {public class FizzBuzzer implements Function<Integer, String> {@Overridepublic String apply(Integer n) {
–     return Integer.toString(n);
+     return numberReplacerFor(n).apply(n);
+   }
+
+   private Function<Integer, String> numberReplacerFor(Integer n) {
+     return n == 3
+         ? i -> “Fizz”
+         : i -> Integer.toString(i);}}

在这里,我认识到我需要根据输入应用两个函数之一。 该代码有效,但需要进行一些清理。 首先,作为垫脚石,我将lambda提取到各个字段中:

import java.util.function.Function;public class FizzBuzzer implements Function<Integer, String> {
+   private final Function<Integer, String> replaceNumberWithStringRepresentation
+       = n -> Integer.toString(n);
+   private final Function<Integer, String> replaceNumberWithFizz
+       = n -> “Fizz”;
+@Overridepublic String apply(Integer n) {return numberReplacerFor(n).apply(n);private Function<Integer, String> numberReplacerFor(Integer n) {return n == 3
–         ? i -> “Fizz”
–         : i -> Integer.toString(i);
+         ? replaceNumberWithFizz
+         : replaceNumberWithStringRepresentation;}}

接下来,我强​​调通过提取一个类将“ 3”和“ Fizz”结合在一起:

public class FizzBuzzer implements Function<Integer, String> {private final Function<Integer, String> replaceNumberWithStringRepresentation= n -> Integer.toString(n);
–   private final Function<Integer, String> replaceNumberWithFizz
–       = n -> “Fizz”;
+   private final Fizzer replaceNumberWithFizz = new Fizzer();@Overridepublic String apply(Integer n) {}private Function<Integer, String> numberReplacerFor(Integer n) {
–     return n == 3
+     return replaceNumberWithFizz.test(n)? replaceNumberWithFizz: replaceNumberWithStringRepresentation;}
+ package remonsinnema.blog.fizzbuzz;
+
+ import java.util.function.Function;
+ import java.util.function.Predicate;
+
+
+ public class Fizzer implements Function<Integer, String>, Predicate<Integer> {
+
+   @Override
+   public boolean test(Integer n) {
+     return n == 3;
+   }
+
+   @Override
+   public String apply(Integer n) {
+     return “Fizz”;
+   }
+
+ }

在这里,我使用标准的Java Predicate功能接口。

要添加“ Buzz”,我需要将代码从单个if (隐藏为三元运算符)推广到循环:

public class WhenFunctionallyFuzzingAndBuzzing {assertFizzBuzz(“1”, 1);assertFizzBuzz(“2”, 2);assertFizzBuzz(“Fizz”, 3);
+     assertFizzBuzz(“4”, 4);
+     assertFizzBuzz(“Buzz”, 5);}private void assertFizzBuzz(String expected, int value) {package remonsinnema.blog.fizzbuzz;
+ import java.util.Arrays;
+ import java.util.Collection;import java.util.function.Function;private final Function<Integer, String> replaceNumberWithStringRepresentation= n -> Integer.toString(n);
–   private final Fizzer replaceNumberWithFizz = new Fizzer();
+   private final Collection<ReplaceNumberWithFixedText> replacers = Arrays.asList(
+       new ReplaceNumberWithFixedText(3, “Fizz”),
+       new ReplaceNumberWithFixedText(5, “Buzz”)
+   );@Overridepublic String apply(Integer n) {}private Function<Integer, String> numberReplacerFor(Integer n) {
–     return replaceNumberWithFizz.test(n)
–         ? replaceNumberWithFizz
–         : replaceNumberWithStringRepresentation;
+     for (ReplaceNumberWithFixedText replacer : replacers) {
+       if (replacer.test(n)) {
+         return replacer;
+       }
+     }
+     return replaceNumberWithStringRepresentation;}}
package remonsinnema.blog.fizzbuzz;
–
– import java.util.function.Function;
– import java.util.function.Predicate;
–
–
– public class Fizzer implements Function<Integer, String>, Predicate<Integer> {
–
–   @Override
–   public boolean test(Integer n) {
–     return n == 3;
–   }
–
–   @Override
–   public String apply(Integer n) {
–     return “Fizz”;
–   }
–
– }
package remonsinnema.blog.fizzbuzz;
+
+ import java.util.function.Function;
+ import java.util.function.Predicate;
+
+
+ public class ReplaceNumberWithFixedText implements Function<Integer, String>,
+     Predicate<Integer> {
+
+   private final int target;
+   private final String replacement;
+
+   public ReplaceNumberWithFixedText(int target, String replacement) {
+     this.target = target;
+     this.replacement = replacement;
+   }
+
+   @Override
+   public boolean test(Integer n) {
+     return n == target;
+   }
+
+   @Override
+   public String apply(Integer n) {
+     return replacement;
+   }
+
+ }

糟糕,旧习惯……那应该是一个循环,而不是循环:

import java.util.function.Function;public class FizzBuzzer implements Function<Integer, String> {
–   private final Function<Integer, String> replaceNumberWithStringRepresentation
+   private final Function<Integer, String> defaultReplacer= n -> Integer.toString(n);private final Collection<ReplaceNumberWithFixedText> replacers = Arrays.asList(new ReplaceNumberWithFixedText(3, “Fizz”),}private Function<Integer, String> numberReplacerFor(Integer n) {
–     for (ReplaceNumberWithFixedText replacer : replacers) {
–       if (replacer.test(n)) {
–         return replacer;
–       }
–     }
–     return replaceNumberWithStringRepresentation;
+     return replacers.stream()
+         .filter(replacer -> replacer.test(n))
+         .map(replacer -> (Function<Integer, String>) replacer)
+         .findFirst()
+         .orElse(defaultReplacer);}}

好多了。 下一个测试是用于倍数的:

public class WhenFunctionallyFuzzingAndBuzzing {assertFizzBuzz(“Fizz”, 3);assertFizzBuzz(“4”, 4);assertFizzBuzz(“Buzz”, 5);
+     assertFizzBuzz(“Fizz”, 6);}private void assertFizzBuzz(String expected, int value) {public class FizzBuzzer implements Function<Integer, String> {private final Function<Integer, String> defaultReplacer= n -> Integer.toString(n);
–   private final Collection<ReplaceNumberWithFixedText> replacers = Arrays.asList(
–       new ReplaceNumberWithFixedText(3, “Fizz”),
–       new ReplaceNumberWithFixedText(5, “Buzz”)
+   private final Collection<ReplaceMultipleWithFixedText> replacers = Arrays.asList(
+       new ReplaceMultipleWithFixedText(3, “Fizz”),
+       new ReplaceMultipleWithFixedText(5, “Buzz”));@Override
+ package remonsinnema.blog.fizzbuzz;
+
+ import java.util.function.Function;
+ import java.util.function.Predicate;
+
+
+ public class ReplaceNumberWithFixedText implements Function<Integer, String>,
+     Predicate<Integer> {
+
+   private final int target;
+   private final String replacement;
+
+   public ReplaceNumberWithFixedText(int target, String replacement) {
+     this.target = target;
+     this.replacement = replacement;
+   }
+
+   @Override
+   public boolean test(Integer n) {
+     return n % target == 0;
+   }
+
+   @Override
+   public String apply(Integer n) {
+     return replacement;
+   }
+
+ }
– package remonsinnema.blog.fizzbuzz;
–
– import java.util.function.Function;
– import java.util.function.Predicate;
–
–
– public class ReplaceNumberWithFixedText implements Function<Integer, String>, Predicate<Integer> {
–
–   private final int target;
–   private final String replacement;
–
–   public ReplaceNumberWithFixedText(int target, String replacement) {
–     this.target = target;
–     this.replacement = replacement;
–   }
–
–   @Override
–   public boolean test(Integer n) {
–     return n == target;
–   }
–
–   @Override
–   public String apply(Integer n) {
–     return replacement;
–   }
–
– }

最后一个测试是结合Fizz和Buzz:

public class WhenFunctionallyFuzzingAndBuzzing {assertFizzBuzz(“4”, 4);assertFizzBuzz(“Buzz”, 5);assertFizzBuzz(“Fizz”, 6);
+     assertFizzBuzz(“7”, 7);
+     assertFizzBuzz(“8”, 8);
+     assertFizzBuzz(“Fizz”, 9);
+     assertFizzBuzz(“Buzz”, 10);
+     assertFizzBuzz(“11”, 11);
+     assertFizzBuzz(“Fizz”, 12);
+     assertFizzBuzz(“13”, 13);
+     assertFizzBuzz(“14”, 14);
+     assertFizzBuzz(“FizzBuzz”, 15);}private void assertFizzBuzz(String expected, int value) {package remonsinnema.blog.fizzbuzz;import java.util.Arrays;import java.util.Collection;import java.util.function.Function;
+ import java.util.stream.Collectors;
+ import java.util.stream.Stream;public class FizzBuzzer implements Function<Integer, String> {@Overridepublic String apply(Integer n) {
–     return numberReplacerFor(n).apply(n);
+     return numberReplacersFor(n)
+         .map(function -> function.apply(n))
+         .collect(Collectors.joining());}
–   private Function<Integer, String> numberReplacerFor(Integer n) {
–     return replacers.stream()
+   private Stream<Function<Integer, String>> numberReplacersFor(Integer n) {
+     return Stream.of(replacers.stream().filter(replacer -> replacer.test(n)).map(replacer -> (Function<Integer, String>) replacer).findFirst()
–         .orElse(defaultReplacer);
+         .orElse(defaultReplacer));}}

我概括了单一Function到一个StreamFunction S,而我应用的map-reduce模式。 我本可以使用.reduce("", (a, b) -> a + b)类的东西来拼写Reduce的部分,但是我认为Collectors.joining()更具表现力。

这还没有通过测试,因为我返回了单个函数的流。 该修复有些棘手,因为我需要知道是否找到了任何适用的替换器函数,并且您必须在不终止stream的情况下才能做到这一点 。 所以我需要使用StreamSupport创建一个新的流:

package remonsinnema.blog.fizzbuzz;import java.util.Arrays;import java.util.Collection;
+ import java.util.Iterator;
+ import java.util.Spliterators;import java.util.function.Function;import java.util.stream.Collectors;import java.util.stream.Stream;
+ import java.util.stream.StreamSupport;public class FizzBuzzer implements Function<Integer, String> {}private Stream<Function<Integer, String>> numberReplacersFor(Integer n) {
–     return Stream.of(replacers.stream()
+     Iterator<Function<Integer, String>> result = replacers.stream().filter(replacer -> replacer.test(n)).map(replacer -> (Function<Integer, String>) replacer)
–         .findFirst()
–         .orElse(defaultReplacer));
+         .iterator();
+     return result.hasNext()
+         ? StreamSupport.stream(Spliterators.spliteratorUnknownSize(result, 0), false)
+         : Stream.of(defaultReplacer);}}

就是这样。 完整代码在GitHub上 。

我从这个小练习中学到了两个教训:

  1. Java附带了一堆功能接口,例如FunctionPredicate ,可以很容易地与流结合以解决各种问题。
  2. if → while 转换的标准变成if → stream在功能世界中if → stream

翻译自: https://www.javacodegeeks.com/2016/08/functional-fizzbuzz-kata-java.html

kata

kata_Java中的功能性FizzBu​​zz Kata相关推荐

  1. Java中的功能性FizzBu​​zz Kata

    不久前,我使用Java 8流和lambda解决了FizzBu​​zz kata问题. 尽管最终结果是可行的,但中间步骤却没有. 我当然可以做得更好. 与往常一样,让我们​​从失败的测试开始: pack ...

  2. FizzBu​​zz Kata与Java流

    在柔道练习仅几周之后,我的儿子感到无聊. 他抱怨说自己没有学任何东西,因为他一遍又一遍地做着同样的事情. 混淆学习和做新事物的不仅仅是幼儿. 例如,有多少软件开发人员通过执行kata或参加dojos来 ...

  3. mockito_使用FizzBu​​zz和Mockito进行单元测试

    mockito 我有时使用FizzBu​​zz向新手演示单元测试的基础. 尽管FizzBu​​zz确实是一个简单的问题,但是它也可以用于演示更高级的单元测试技术,例如模拟. FizzBu​​zz Ka ...

  4. mockito 单元测试_使用FizzBu​​zz和Mockito进行单元测试

    mockito 单元测试 我有时使用FizzBu​​zz向新手演示单元测试的基础. 尽管FizzBu​​zz确实是一个简单的问题,但它也可以用于演示更高级的单元测试技术,例如模拟 . FizzBu​​ ...

  5. 使用FizzBu​​zz和Mockito进行单元测试

    我有时使用FizzBu​​zz向新手演示单元测试的基础. 尽管FizzBu​​zz确实是一个简单的问题,但是它也可以用于演示更高级的单元测试技术,例如模拟 . FizzBu​​zz Kata: &qu ...

  6. deepin中zz_如何解决R中的FizzBu​​zz问题

    deepin中zz The FizzBuzz problem is a classic test given in coding interviews. The task is simple: Fiz ...

  7. kata_FizzBu​​zz Kata与Java流

    kata 在柔道练习仅几周之后,我的儿子感到无聊. 他抱怨说自己没有学任何东西,因为他一遍又一遍地做着同样的事情. 混淆学习和做新事物的不仅是幼儿. 例如,有多少软件开发人员通过执行kata或参加do ...

  8. 隐马尔可夫模型中的Viterbi算法zz

    隐马尔可夫模型中的Viterbi算法zz 这篇文章简单描述一下Viterbi算法--一年之前我听过它的名字,直到两周之前才花了一点时间研究了个皮毛,在这里做个简单检讨.先用一句话来简单描述一下:给出一 ...

  9. [c、c++]宏中#和##的用法(zz)

    http://blog.csdn.net/blackbillow/article/details/3850587 [c.c++]宏中"#"和"##"的用法(zz ...

最新文章

  1. kali Linux metasploit进入msfgui
  2. 19款绚丽实用的jQuery/CSS3侧边栏菜单
  3. php光标添加,JS在可编辑的div中的光标位置插入内容的方法_javascript技巧
  4. 【转】vue项目打包上传的步骤和方法
  5. cpu卡操作协议iso14443协议
  6. 基于智能的网络空间安全防御
  7. AWS S3 Windows系统下的文件夹上传基于python
  8. ThinkPHP讲解(一)框架基础
  9. 心里装着你,思念就很美(我要做一个文艺范儿的程序员)
  10. Linux下安装 卸载mysql57 msyql80
  11. ftp工具哪个好,推荐8个超级好用而且免费的ftp工具,支持中文版windows系统的。
  12. SSM 运行报错Failed to load resource: the server responded with a status of 404 (Not Found)
  13. Iterative Deep Learning论文简读
  14. python 正数变成负数_初一数学上册第一章有理数1.1正数和负数基础知识概括及同步练习题含解析...
  15. tp5的时间查询,查询时间戳是否在某一天中
  16. 数据结构与算法实验6——图论 7-9 哥尼斯堡的“七桥问题”
  17. Android 仪表盘 图片 中心 旋转
  18. 利用“WinRAR”创建自解压文件
  19. 底层放弃教育,中产过度焦虑,上层不玩中国高考
  20. Linux计划任务要怎么弄?

热门文章

  1. YBTOJ洛谷P2042:维护数列(平衡树)
  2. YBTOJ:魔法数字(数位dp)
  3. jzoj3846-七天使的通讯【二分图判定】
  4. 欢乐纪中A组周六赛【2019.3.30】
  5. 【倍增】【线段树】雨林跳跃(luogu 7599[APIO 2021 T2])
  6. 【结论】立体井字棋(jzoj 2124)
  7. Spark入门(十四)之分组求最大值
  8. Http 持久连接与 HttpClient 连接池
  9. 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其他的空间。表中不允许又重复的数据
  10. Hibernate基本概念 (4)