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
。在 filter
和 findFirst
中,它在第一条错误消息后停止。它是评论中提到的 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;
}
}
}
我有一个 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
。在 filter
和 findFirst
中,它在第一条错误消息后停止。它是评论中提到的 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;
}
}
}