功能性Java 8与传统Java

时间:2018-06-22 22:36:33

标签: java java-8 functional-programming

几周以来,我一直在尝试使用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);
    }
}
}

2 个答案:

答案 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,但本质上就是这些。