Break or return from java 8 map reduce 在功能界面

Break or return from java 8 map reduce in functional interface

我有一个 java 8 功能接口,它接受应用于对象的验证器列表和 returns 验证结果。验证结果在reduce阶段累积。代码如下:

public interface LogicalTableValidator extends Function<LogicalTable, ValidationResult> {

    static LogicalTableValidator addAll(LogicalTableValidator... validators) {

        //  Need to break out of this validator stream, based on the criticality of a particular validation error
        return logicalTable -> Arrays.stream(validators).map(v -> v.apply(logicalTable))
                .reduce(new ValidationResult(logicalTable.getUid()), (validationResult, currentResult) -> {
                    validationResult.addValidationMessages(currentResult.getValidationMessages());
                    return validationResult;
                });

    }

}

从这里调用此验证逻辑

LogicalTableValidator logicalTableValidators = LogicalTableValidator.addAll(getValidators());
List<ValidationResult> ltValidationResults = logicalTables.stream()
                                                          .parallel()
                                                          .map(logicalTableValidators)
                                                          .collect(Collectors.toList());

我面临的问题是,我无法有条件地中断验证逻辑。当我在 logicalObject 上应用验证器时就是这种情况,如果验证失败并出现严重错误,我不需要 运行 其余验证器。相反,我需要在那里停止验证过程。

解决方法是不使用 lambda 表达式进行验证,而是使用以下代码。

        return new LogicalTableValidator() {

            @Override
            public ValidationResult apply(LogicalTable t) {
                ValidationResult result = new ValidationResult(t.getUid());
                for (LogicalTableValidator validator : validators) {
                    ValidationResult currentResult = validator.apply(t);
                    List<ValidationMessage> messages = currentResult.getValidationMessages();
                    Boolean exit = false;
                    for (ValidationMessage message : messages) {
                        if(StringUtils.equalsIgnoreCase(message.getSeverity(),  "1")) {
                            exit = true;
                            break;
                        }
                    }
                    result.addValidationMessages(currentResult.getValidationMessages());
                    if (exit) break;
                }
                return result;
            }

        };

看来,在函数式接口中不使用 lambda 表达式,违背了使用函数式接口的目的,但我想不出一种有条件地跳出验证循环的方法。我可以使用其他替代方法吗?此代码是否应该以不同的方式构建?

有两种截然不同的情况:1. 中断 logicalTables 流和 2. 中断 validators 流。

对于 logicalTables,您的数据流是并行的,即使中断是可能的,您也会获得可能不同的结果。

对于validators流,Stream.takeWhile似乎是最接近纯基于流的解决方案。不幸的是,它在 JDK 中,因为 Java 9 而且它不包含无效的 ValidationResult 到结果流中。外部库中可能存在替代方案,尽管目前命令式代码在我看来是最简单和可读性最强的。

您可以尝试如下操作。在 peek 中收集 ValidationMessages。在 filterfindFirst 中,它在第一条错误消息后停止。它是评论中提到的 takeWhile 的替代品,您还可以检查 this.

public interface LogicalTableValidator extends Function<LogicalTable, ValidationResult> {

    static LogicalTableValidator addAll(LogicalTableValidator... validators) {

        logicalTable -> {
            ValidationResult result = new ValidationResult(logicalTable.getUid());
            Arrays.stream(validators).map(v -> v.apply(logicalTable))
                    .peek(currentResult -> result.addValidationMessages(currentResult.getValidationMessages()))
                    .filter(currentResult -> currentResult.getValidationMessages().stream()
                            .filter(message -> StringUtils.equalsIgnoreCase(message.getSeverity(), "1"))
                            .count() > 0)
                    .findFirst()
                    .orElse(null);
            return result;
        }
    }

}