我想使用Java 8 Streams替换以下for-each循环:
for (Rule rule : this.rules) {
if (rule.getCondition().evaluate(rule, record)) {
Records.emit(collector, outputStreamMapping.get(rule.getOutputStream()), tuple, recordId, record);
collector.ack(tuple);
ruleApplied = true;
break;
}
}
if (!ruleApplied) {
LOGGER.warn("No rule was applied to record {}", record);
LOGGER.debug("Rules: {}", this.rules);
ErrorReporter.emitErrorNode(this.collector, recordId, componentName,
"No matching rule for record " + record, record);
collector.fail(tuple);
}
我想迭代一组规则,并评估每个规则的条件。如果条件适用,我会对该记录采取行动并停止处理。如果没有应用规则,那么我想记录它并对记录执行不同的处理。
但是,我不确定如何做到这一点。任何帮助和解释将不胜感激。编辑:
我试过这个:
this.rules.stream().filter(rule -> rule.getCondition().evaluate(rule, record)).forEach((rule) -> {
Records.emit(collector, outputStreamMapping.get(rule.getOutputStream()), tuple, recordId, record);
collector.ack(tuple);
ruleApplied = true;
break;
});
当然,它并不喜欢break语句,并抱怨ruleApplied
不是最终的,因为它在lambda范围之外声明。
根据我所看到的答案,似乎循环是最干净的方式。我不确定是否有其他流构造允许我以与在基本循环中所做的不同的方式封装逻辑(即,中断和跟踪布尔)。
EDIT2:
以下是基于此主题建议的解决方案:
Optional<Rule> possibleRule = rules.stream().filter(rule -> rule.getCondition().evaluate(rule, record))
.findFirst();
if (possibleRule.isPresent()) {
Records.emit(collector, outputStreamMapping.get(possibleRule.get().getOutputStream()), tuple, recordId,
record);
collector.ack(tuple);
} else {
LOGGER.warn("No rule was applied to record {}", record);
LOGGER.debug("Rules: {}", this.rules);
ErrorReporter.emitErrorNode(this.collector, recordId, componentName,
"No matching rule for record " + record, record);
collector.fail(tuple);
}
答案 0 :(得分:6)
你可以做到
Optional<Rule> rule = rules.stream().
.filter(rule -> rule.getCondition().evaluate(rule, record))
.findFirst();
if (rule.isPresent()) {
Records.emit(collector, outputStreamMapping.get(rule.get().getOutputStream()),
tuple, recordId, record);
collector.ack(tuple);
ruleApplied = true;
}
答案 1 :(得分:1)
您应该可以使用Stream
anyMatch
方法和执行Predicate
等必要副作用的Records.emit
来执行此操作。< / p>
boolean ruleApplied = this.rules.stream().anyMatch(
rule ->
{
boolean match = rule.getCondition().evaluate(rule, record);
if (match)
{
Records.emit(collector, outputStreamMapping.get(rule.getOutputStream()), tuple, recordId, record);
collector.ack(tuple);
}
return match;
}
);
anyMatch
method是一种短路操作,会在Predicate
返回true
时停止处理。短路将满足您的break
行为。
返回此流的任何元素是否与提供的谓词匹配。如果不是确定结果所必需的,则不能评估所有元素的谓词。如果流为空,则返回false并且不评估谓词。
这是一种短路终端操作。