我有一个Validator
接口,它提供了一个isValid(Thing)
方法,返回一个ValidationResult
,其中包含一个布尔值和一条原因消息。
我想创建此接口的
ValidatorAggregator
实现,它跨多个Validator
s执行OR(如果任何Validator
返回正结果,则结果为正)。如果任何验证器成功,我想短路并只返回其结果。如果没有验证器成功,我想返回所有失败消息。
我可以使用流和
findFirst()简洁地实现这一点。orElse(…)
但是如果findFirst
返回空值,则使用此模式我将丢失所有中间结果:
public ValidationResult isValid(final Thing thing) {
return validators.stream()
.map(v -> validator.isValid(thing))
.filter(ValidationResult::isValid)
.findFirst()
.orElseGet(() -> new ValidationResult(false, "All validators failed'));
}
是否有任何方法可以使用流捕获失败的结果,或者确实比下面更简洁?
public ValidationResult isValid(final Thing thing) {
final Set<ValidationResult> failedResults = new HashSet<>();
for (Validator validator : validators) {
final ValidationResult result = validator.isValid(thing);
if (result.isValid()) {
return result;
}
failedResults.add(result);
}
return new ValidationResult(false, "No successful validator: " + failedResults);
// (assume failedResults stringifies nicely)
}
编辑:根据评论,我同意我试图做的是过早的优化(特别是因为这些验证器非常轻量级)。我可能会采用类似于Holger的解决方案,即计算所有验证并划分为成功/不成功的结果。
这被标记为你能把一个流分成两个流吗?和
分区By
答案排序是,但我认为这个问题是问,讨论回答,一个不同的问题。
没有一个完美的解决方案能以同样的效率处理所有案件。即使是满足短路和只处理一次验证器的条件的循环变量,也有创建和填充集合的缺点,如果只有一次验证成功,这些集合可能是不必要的。
选择取决于与操作相关的实际成本以及至少一次成功验证的可能性。如果以最佳性能处理常见案例,可能会超过解决方案对处理不常见案例的惩罚。
所以
// you may use this if the likelihood of a success is high; assumes
// reasonable costs for the validation and consists (repeatable) results
public ValidationResult isValid(final Thing thing) {
return validators.stream()
.map(v -> v.isValid(thing))
.filter(ValidationResult::isValid)
.findFirst()
.orElseGet(() -> new ValidationResult(false, "All validators failed"
+ validators.stream().map(v -> v.isValid(thing)).collect(Collectors.toSet())));
}
// you may use this if the likelihood of a success is
// very low and/or you intent to utilize parallel processing
public ValidationResult isValid(final Thing thing) {
Map<Boolean,Set<ValidationResult>> results = validators.stream()
.map(v -> v.isValid(thing))
.collect(Collectors.partitioningBy(ValidationResult::isValid, Collectors.toSet()));
return results.get(true).stream().findAny()
.orElseGet(() -> new ValidationResult(false,
"No successful validator: "+results.get(false)));
}
// if chances of successful validation are mixed or unpredictable
// or validation is so expensive that everything else doesn't matter
// stay with the loop
public ValidationResult isValid(final Thing thing) {
final Set<ValidationResult> failedResults = new HashSet<>();
for (Validator validator : validators) {
final ValidationResult result = validator.isValid(thing);
if (result.isValid()) {
return result;
}
failedResults.add(result);
}
return new ValidationResult(false, "No successful validator: " + failedResults);
}
考虑对列表进行排序,这样成功几率更高的验证器就在开始时…
我有一个C#代码,使用Elastic搜索类型,它将匹配两个字段。我用的是NEST软件包。 问题是,无论我传入什么文本,它都会返回所有结果。我错过了什么?
你好,我在Java中使用正则表达式时遇到了一个问题。 我试图解析这个: 使用此代码(模式匹配器) 我的问题是,我的regexp只返回模式的第一次出现,即使我有一段时间(matcher.find())。。
我正在为我的 REST API 控制器编写测试,我需要检查返回的 对象中的 值,请参阅此测试方法: 但是测试产生了这个错误: 似乎ID被正确返回,但被序列化为不同的结构。 我的代码有什么问题?
问题内容: 做一个简单的测试时,我就在用Java编写正则表达式 但是在JavaScript中 这里发生了什么?我可以使我的Java regex模式“ q”的行为与JavaScript相同吗? 问题答案: 在JavaScript中,返回与使用的正则表达式匹配的子字符串。在Java中,检查整个字符串是否与正则表达式匹配。 如果要查找与正则表达式匹配的子字符串,请使用Pattern和Matcher类,例
我陷入了java流操作的边缘案例... 我想对以下行为进行编码:“从一个任意的水果篮子中,收集20个最小的,除了最小的梨,因为我们不想那样。” 额外的奖励:来的篮子可能没有任何梨。 null 我不能使用本地布尔值并在筛选第一个pear后将其设置为,因为lambda中的所有局部变量都必须是final的。 最坏的情况是,我可以将篮子一分为二,梨和非梨,对梨进行排序,如果有的话,适当地将它们子列表。这看
当Callable返回与条件匹配的结果时,是否有一种方法可以停止Javas ExecuterService? 我有以下算法(代码A): 平均而言,functionB的运行速度是functionA的5倍(在8个内核上)。 这很好,但不完美。在functionA中,someFunction()在找到结果!=null之前平均被调用大约20次。在functionB中,someFunction()总是被调用