功能java 8与传统java
几周来,我一直在尝试使用java进行函数式编程。我在“ValidateFileFunctionly”和“ValidateFileRegulary”下面创建了两个函数,它们执行相同的验证。第一种是使用谓词的功能性方式(我们可以假设供应商,这里也包括消费者),而第二种是使用传统的java方式 2018年我应该走哪条路。 我应该尝试在代码中的任何地方使用函数式编程,就像在“ValidateFileFunctional”中一样,还是只使用流功能java 8与传统java,java,java-8,functional-programming,Java,Java 8,Functional Programming,几周来,我一直在尝试使用java进行函数式编程。我在“ValidateFileFunctionly”和“ValidateFileRegulary”下面创建了两个函数,它们执行相同的验证。第一种是使用谓词的功能性方式(我们可以假设供应商,这里也包括消费者),而第二种是使用传统的java方式 2018年我应该走哪条路。 我应该尝试在代码中的任何地方使用函数式编程,就像在“ValidateFileFunctional”中一样,还是只使用流 public class Main { private fi
public class Main {
private final String INVALID_FILE_NAME_LENGTH = "INVALID FILE NAME LENGTH";
private final String INVALID_FILE_EXTENSION = "INVALID FILE EXTENSION";
private final String INVALID_FILE_SIZE = "INVALID FILE SIZE";
public static void main(String... args) {
File file = new File("text.pdf");
Main main = new Main();
main.validateFileFunctionally(file);
main.validateFileRegularly(file);
}
private void validateFileFunctionally(File file) {
BiPredicate<File, Integer> validateFileName = (f, maxLength) -> f.getName().length() < maxLength;
BiPredicate<File, String> validateExtension = (f, type) -> f.getName().endsWith(type);
BiPredicate<File, Integer> validateSize = (f, maxSize) -> f.length() <= maxSize;
BiConsumer<Boolean, String> throwExceptionIfInvalid = (isValid, errorMessage) -> {
if(!isValid) {
throw new InvalidFileException(errorMessage);
}
};
throwExceptionIfInvalid.accept(validateFileName.test(file, 20), INVALID_FILE_NAME_LENGTH);
throwExceptionIfInvalid.accept(validateExtension.test(file, ".pdf") || validateExtension.test(file, ".csv"), INVALID_FILE_EXTENSION);
throwExceptionIfInvalid.accept(validateSize.test(file, 20), INVALID_FILE_SIZE);
}
private void validateFileRegularly(File file) {
if (file.getName().length() > 20) {
throw new InvalidFileException("INVALID FILE NAME LENGTH");
} else if (!file.getName().endsWith(".pdf") && !file.getName().endsWith(".csv")) {
throw new InvalidFileException("INVALID FILE NAME LENGTH");
} else if (file.length() > 20) {
throw new InvalidFileException("INVALID FILE NAME LENGTH");
}
}
class InvalidFileException extends RuntimeException {
public InvalidFileException(String message) {
super(message);
}
}
}
公共类主{
私有最终字符串无效\u FILE\u NAME\u LENGTH=“无效文件名长度”;
私有最终字符串无效\u文件\u扩展名=“无效文件扩展名”;
私有最终字符串无效\u FILE\u SIZE=“无效文件大小”;
公共静态void main(字符串…参数){
文件=新文件(“text.pdf”);
Main Main=新Main();
main.validateFileFunction(文件);
main.validateFileRegulary(文件);
}
私有void验证功能(文件){
BiPredicate validateFileName=(f,maxLength)->f.getName().length()f.getName().endsWith(type);
BiPredicate validateSize=(f,maxSize)->f.length(){
如果(!isValid){
抛出新的InvalidFileException(errorMessage);
}
};
ThroweExceptionIFInvalid.accept(validateFileName.test(文件,20),无效的\u文件名\u长度);
通过ExceptionIFInvalid.accept(validateExtension.test(文件“.pdf”)| | | validateExtension.test(文件“.csv”),文件扩展名无效;
ThroweExceptionIFInvalid.accept(validateSize.test(文件,20),文件大小无效;
}
私有void validateFileRegulary(文件){
if(file.getName().length()>20){
抛出新的InvalidFileException(“无效文件名长度”);
}如果(!file.getName().endsWith(“.pdf”)和(&!file.getName().endsWith(.csv)),则为else{
抛出新的InvalidFileException(“无效文件名长度”);
}else if(file.length()>20){
抛出新的InvalidFileException(“无效文件名长度”);
}
}
类InvalidFileException扩展了RuntimeException{
公共InvalidFileException(字符串消息){
超级(信息);
}
}
}
Dah,恐怕这是我的心病。不要因为它是最新的/很酷的东西就到处塞满函数式的东西——这只会让你的代码很难阅读,也很不传统。Java8函数库只是另一个可用的工具,它允许您在许多情况下编写更干净、更简洁的代码。你当然不应该只使用它们
以您的案例为例—链式if语句可能仍然不是实现上述目标的最佳方式,但我可以看到这一点,并在几秒钟内准确地知道发生了什么
同时,函数示例也很奇怪。它的时间更长,不太清楚发生了什么,并且没有提供真正的优势。在本例中,我看不出有任何一种情况可以使用它。您应该在任何有意义的地方应用函数式编程,不要使用粗体语句,如:
“我应该尝试在代码中的任何地方使用FP”
“我应该只使用流进行编码”
validateFileFunction
只是企业级版本的validateFileRegulary
简单地说,您获取了一段必需的代码,并通过将其包装到FP基础设施中重新编写了它,而FP并不是这样做的
FP是通过从小而可预测的构建块/值构建代码来消除运行时的不确定性,而不是尽可能地放置lambda表达式
在您的示例中,可以通过放弃异常处理并将验证结果表示为值来实现这一点:
private Result validateFileRegularly(File file) {
if (file.getName().length() > 20) {
return Result.failed("INVALID FILE NAME LENGTH");
} else if (!file.getName().endsWith(".pdf") && !file.getName().endsWith(".csv")) {
return Result.failed("INVALID FILE NAME LENGTH");
} else if (file.length() > 20) {
return Result.failed("INVALID FILE NAME LENGTH");
}
return Result.ok();
}
当然,我们可以使用更复杂的语法,或者更复杂的基于应用程序的验证API,但本质上就是这样。无论谁否决了,这不是一个特别好的问题,但它是有效的,因为@Michael Berry选择的答案对于那些试图理解何时不使用功能性Java 8的人来说是一个有用的回答。这个问题应该发布在StackExchange CodeReviews上(我没有投反对票,但我会支持它)。我知道函数式编程的可读性不如命令式编程的例子,但这个例子的代码编写得很糟糕。不仅方法
validateFileFunction
,而且调用(如果调用时考虑了函数,则看起来不会是这样)。@CoronA:谢谢您的评论。您可以假设这两种方法存在于服务/组件中,然后被应用程序的其他部分(例如控制器)使用,以验证上传的文件。你能告诉我你是如何在功能上和必要性上编写它的吗?@RohitJain:你的设计是你有一个抛出异常的服务。使其功能化的一种方法是拥有一个文件流,过滤掉无效的文件(或者将它们转换为错误对象,然后进行处理)。表明您没有真正发挥作用的一个指标是方法validateXXX
没有返回任何内容。这意味着它们依赖于副作用。如果您想知道如何做得更好,请将您的示例发布在StackExchange代码审阅上。这不是“功能等价物”。。。这是另一个使用函数式语言功能的命令式版本。函数等价物可能涉及使用验证
应用函数或单子(取决于用例),从而变得更加简洁易读。