kata_Java中的功能性FizzBu​​zz Kata

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 【随想录】(三)源文件编译流程,静态库与动态库编译

预处理 : 完成宏替换&#xff0c;文件引入&#xff1b;以及去除空行&#xff0c;注释等&#xff0c;为下一步编译做准备。也就是对各种预处理命令进行处理&#xff0c;包括头文件的包含&#xff0c;宏定义扩展&#xff0c;条件编译的选择。 gcc -E test.c -o test…

python字典查询多个值_python – 在Pandas Dataframe中查找多个字典键并返回多个匹配值...

如果我的格式化关闭,第一次发布如此道歉.这是我的问题&#xff1a;我创建了一个包含多行文本的Pandas数据框&#xff1a;d {keywords :[cheap shoes, luxury shoes, cheap hiking shoes]}keywords pd.DataFrame(d,columns[keywords])In [7]: keywordsOut[7]:keywords0 cheap …

hibernate jpa_使用Hibernate(JPA)一键式删除

hibernate jpa在旧版本的Hibernate中&#xff0c;我可以看到手册中指示的一键式删除 。 但是较新的版本不再包含此部分。 我不知道为什么。 因此&#xff0c;在这篇文章中&#xff0c;我来看看它是否仍然有效。 一键式删除部分显示&#xff1a; 有时一个接一个地删除收集元素…

python测试开发实战_《python测试开发实战》基于pytest基础部分实例1-Hello

要求实现如下命令行接口python 1hello.py -husage: 1hello.py [-h] [-n NAME]Say hellooptional arguments:-h, --help show this help message and exit-n NAME, --name NAME Name to greet没有参数时输出Hello, World!$python 1hello.pyHello, World!有参数时输出Hello, 人名…

kafka 发布订阅_在Kafka中发布订阅模型

kafka 发布订阅这是第四个柱中的一系列关于同步客户端集成与异步系统&#xff08; 1&#xff0c; 2&#xff0c; 3 &#xff09;。 在这里&#xff0c;我们将尝试了解Kafka的工作方式&#xff0c;以便正确利用其发布-订阅实现。 卡夫卡概念 根据官方文件 &#xff1a; Kafka是…

python socket recvfrom_Python socket学习笔记(一)

最近在看 Python的视频&#xff0c;针对socket 编程做一个笔记一、socket是什么&#xff1f;socket 通常也称为“套接字”&#xff0c;用于描述 IP 地址和端口&#xff0c;是一个通讯链的句柄。应用程序通常通过 “套接字”向网络发出请求或者应答网络请求。说白了&#xff0c;…

dynamodb java_使用Java更新DynamoDB项

dynamodb java在上一篇文章中&#xff0c;我们继续使用Java将项目插入DynamoDB。 DynamoDB还支持更新项目。 我们将使用Login表获取更新示例。 发布更新时&#xff0c;必须指定要更新的项目的主键。 public void updateName(String email,String fullName) {Map<String,A…

apache camel_使用Apache Camel进行负载平衡

apache camel在此示例中&#xff0c;我们将向您展示如何使用Apache Camel作为系统的负载平衡器。 在计算机世界中&#xff0c;负载平衡器是一种充当反向代理并在许多服务器之间分配网络或应用程序流量的设备。 负载平衡器用于增加容量&#xff08;并发用户&#xff09;和应用程…

lombok 自动使用_Lombok,自动值和不可变项

lombok 自动使用我喜欢布兰登&#xff08;Brandon &#xff09;在博客文章中比较Project Lombok &#xff0c; AutoValue和Immutables的建议 &#xff0c;而这篇文章试图做到这一点。 我已经简要概述了Project Lombok &#xff0c; AutoValue和Immutables &#xff0c;但是这篇…

邮箱批量登录接验证码_记一次莫名的需求(临时邮箱|企业邮箱)

目录&#xff1a;前言行情伪需求过程1.前戏2.买域名3.网易企业邮箱4.模糊的需求5.晚饭后6.临时邮箱16.临时邮箱27.域名版临时邮箱8.遇见问题8.1.DNSPOD8.2.换种思路拓展1.思路2.后续2.1.简单2.2.自建临时邮箱后话记一次需求不明的亏看完这篇文章你会学到&#xff1a; 免费企业邮…

【四】初步预测

import time from lxml import etree from collections import defaultdict import math import requests from matplotlib import pyplot as plt import pandas as pd import datetimed = defaultdict(list) listp = list()# 90+进球球队 setp = set()Allset = set()def httpg…

java 补充日期_Java 9对可选的补充

java 补充日期哇&#xff0c;人们真的对Java 9对Stream API的添加感兴趣。 想要更多&#xff1f; 让我们看一下…… 可选的 可选::流 无需解释&#xff1a; Stream<T> stream();想到的第一个词是&#xff1a; 终于 &#xff01; 最后&#xff0c;我们可以轻松地从可选…

msf如何升级_Kali linux 2016.2(Rolling)中的Metasploit如何更新与目录结构初步认识...

如何更新MSF1、Windows平台方法1&#xff1a;运行msfupdate.bat在msfconsole里执行命令svn update或者方法2&#xff1a;2、unix/linux平台方法1&#xff1a;运行msfupdate即可。方法2&#xff1a;(比较麻烦)安装subversion客户端(--with-ssl)&#xff0c;之后连接CVS server进…

【五】每个球队胜率统计

import time from lxml import etree from collections import defaultdict import math import requests from matplotlib import pyplot as plt import pandas as pd import datetimed = defaultdict(list) listp = list()# 近七天比赛所有球队 listall = list()# 近七天所有…

jaxb注解使用_使用JAXB的简介

jaxb注解使用我正在将一些依赖于Apache XMLBeans的模块迁移到JAXB。 这是令人兴奋和充满挑战的几天。 我想记下我遇到的一些重要事情&#xff0c;以供将来可能会发现有用的任何人使用。 首先&#xff0c;让我们来看一下设置用于JAXB代码生成的maven插件。 在撰写本文时&#x…

离散信号的抽取和内插例题_信号与系统例题分析

第1章 信号及其基本运算1.1 内容要点1.2 公式摘要1.3 例题分析例1.1 连续时间信号与波形例1.2 离散时间信号与波形例1.3 信号的积分运算例1.4 单位冲激信号的筛选特性例1.5 信号的平移例1.6 信号的求和、积分运算例1.7 卷积的两种计算方法例1.8 卷积的位移特性例1.9 卷积概念的…

dynamodb java_使用Java扫描DynamoDB项目

dynamodb java在之前的文章中&#xff0c;我们介绍了如何查询DynamoDB数据库 查询DynamoDB第1部分 查询DynamoDB第2部分 。 除了发出查询之外&#xff0c;DynamoDB还提供扫描功能。 扫描所做的是获取您在DynamoDB表上可能拥有的所有项目。 因此&#xff0c;扫描不需要任何基…

【Python科学计算系列】行列式

1.二元线性方程组求解 import numpy as np a np.array([[3, -2], [2, 1]]) b np.array([12, 1]) d np.linalg.solve(a, b) print(d) 2.三阶行列式求值 import numpy as np a np.array([[1, 2, -4], [-2, 2, 1], [-3, 4, -2]]) d np.linalg.det(a) print(d) 3.行列式的余…

python写的hadoop实战_Hadoop实战

Hadoop实战1 Hadoop简介1.1 什么是Hadoop1.1.1 Hadoop概述1.1.2 Hadoop的历史1.1.3 Hadoop的功能与作用1.1.4 Hadoop的优势1.1.5 Hadoop的应用现状和发展趋势1.2 Hadoop项目及其结构1.3 Hadoop的体系结构1.3.1 HDFS的体系结构1.3.2 MapReduce的体系结构1.4 Hadoop与分布式开发1…

mfc 弹簧_弹簧活性样品

mfc 弹簧Spring-Reactive旨在为基于Spring的项目带来响应式编程支持 &#xff0c;并且有望在Spring 5的时间表中提供。 我的意图是使用此模型为REST端点行使一些非常基本的签名。 在继续之前&#xff0c;请允许我确认整个样本完全基于塞巴斯蒂安德勒兹&#xff08;SbastienDel…