我有以下两个实现的接口:
public interface Parser {
void parse();
boolean canParse(String message);
}
class StackParser implements Parser {
public void parse(){
System.out.println("Parsing stackoverflow");
}
public boolean canParse(String message){
return message.equals("stackoverflow");
}
}
class YoutubeParser implements Parser {
public void parse() {
System.out.println("Parsing youtube");
}
public boolean canParse(String message) {
return message.equals("youtube");
}
}
我检查传入的消息并解析“StackOverflow”
或“YouTube”
:
public class Main {
private List<Parser> parsers;
public static void main(String[] args) {
new Main().doSomething("youtube");
}
void doSomething(String message){
parsers.stream()
.filter(p -> p.canParse(message))
.forEach(p -> p.parse());
}
}
好吧,相当不错。 但是如果消息不是“StackOverflow”
或“YouTube”
呢? 应用程序将处于静默状态,但如果没有找到匹配项,我想发送另一条默认消息,例如“我无法解析此Web!”
。
我知道这不起作用(即使编译),但它也应该只打印一次“我不能解析此Web”
,而不是针对每个false
条件。
parsers.stream()
.filter(p -> {
if (p.canParse(message) == false) {
System.out.println("I can't parse it!");
}
})
.forEach(p -> p.parse());
我怎么能做到呢?
这是关于何时使用可选#orelse
或可选#orelseThrow
方法的完美示例。 您希望检查是否满足某些条件,因此进行筛选,尝试返回单个结果。 如果一个不存在,则其他一些条件为真,应返回。
try {
Parser parser = parsers.stream()
.filter(p -> parser.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
您可以在内部简单地使用forEach if-else
parsers.forEach(p -> {
if (!p.canParse(message)) {
System.out.println("I can't parse it!");
} else {
p.parse();
}
});
如果一次只有一个解析器可以解析消息,您可以添加一个默认解析器:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
然后通过
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
或者删除DefaultParser并执行以下操作
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}