I want to replace the following for-each loop using Java 8 Streams:
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);
}
I want to iterate over a set of Rules, and evaluate each Rule's Condition. If the condition applies, I act on that record and stop processing. If no Rules are applied, then I want to log that and perform different processing of the record.
I'm not exactly sure how to do this, though. Any help and explanation would be greatly appreciated.
EDIT:
I've tried this:
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;
});
It doesn't like the break statement, of course, and also complains about ruleApplied not being final since it's declared outside the scope of the lambda.
Based on the answers I'm seeing, it seems as though the loop is the cleanest way to do this. I wasn't sure if there were other stream constructs that would allow me to encapsulate the logic (i.e., the break and the tracking boolean) in a different manner than how I did in the basic loop.
EDIT2:
Here's my solution based on this thread's advice:
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);
}
ruleApplied = trueline in particular is going to be difficult. The result is not going to be as nice as the code you already have.