几周以来,我一直在尝试使用Java进行函数式编程。我在“ validateFileFunctionally”和“ validateFileRegularly”下面创建了两个函数,它们执行相同的验证。第一个使用谓词在功能上起作用(我们也可以在这里假设供应商,消费者),第二个以传统的Java方式工作。
2018年我应该走哪条路。 并且我应该尝试在代码中的各处使用函数式编程(如在“ validateFileFunctionally”中完成的操作)还是仅对Streams使用?
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);
}
}
}
答案 0 :(得分:2)
恐怕这是我的宠儿。不要仅仅因为它是最新的新奇/有趣的东西而在所有地方塞满功能性东西-这只会使您的代码难以阅读且不合常规。 Java 8功能库只是您提供的另一种工具,使您可以在许多情况下编写更简洁,更简洁的代码。您当然不应该只打算使用它们。
以您的情况为例-链式if语句可能仍然不是实现上述目标的最佳方法,但是我可以仔细观察一下,并在几秒钟内确切地知道发生了什么。
同时,功能示例只是-相当奇怪。它的时间更长,发生的情况不太明显,并且没有任何真正的优势。我看不到使用此示例中所示的任何一种情况。
答案 1 :(得分:0)
您应该在有意义的地方应用函数式编程,并远离粗体语句,如:
"I should try to use FP everywhere in my code"
"I should code only with Streams"
但是,请记住,此示例根本不起作用-validateFileFunctionally
只是validateFileRegularly
的企业级版本
简而言之,您使用了一条命令性代码并将其包装到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,但本质上就是这些。