我想使用Java 8,如何在java 8中将这种命令式风格转变为函数式风格Optional ?
例如,假设 exchange.getIn().getBody() 可能为 null,也可能不是。
String color = null;
if(exchange.getIn().getBody() instanceof Foo) {
color = "toFoo";
} else if(exchange.getIn().getBody() instanceof Bar){
color = "toBar";
}
也许是这样的东西,但我需要它在一个衬垫中。
Optional.ofNullable(exchange.getIn().getBody())
.filter(body -> body instanceof Foo)
.map(body -> "toFoo");
我的问题是映射已经是一个字符串,所以我无法将其变成一个衬里:
Optional.ofNullable(exchange.getIn().getBody())
.filter(body -> body instanceof Foo)
.map(body -> "toFoo")
.orElse(exchange.getIn().getBody()) //this part is problem, already String
.filter(body -> body instanceof Bar)
.map(body -> "toBar");
最佳答案
您想要做的是模式匹配,这不是 Optional
的用途。您可以滥用Optional
来获得产生所需结果的东西,例如
Object o=exchange.getIn().getBody();
String color=Optional.ofNullable(o).filter(Foo.class::isInstance).map(x->"toFoo")
.orElseGet(()->Optional.ofNullable(o).filter(Bar.class::isInstance).map(x->"toBar")
.orElse("fallback"));
但这显然不是真正的胜利,特别是如果您考虑添加更多案例时会发生什么。
实现目标的一种方法是通过 Map
将谓词和结果关联起来:
Map<Predicate<Object>,String> alternatives=new HashMap<>();
alternatives.put(Bar.class::isInstance, "toBar");
alternatives.put(Foo.class::isInstance, "toFoo");
Object o=exchange.getIn().getBody();
String color=alternatives.entrySet().stream()
.filter(e->e.getKey().test(o))
.findAny().map(Map.Entry::getValue).orElse("fallback");
这会执行线性搜索(没有特定的顺序,因此谓词必须是分离的),这对于少量情况非常有效,并且您可以添加另一个情况,就像简单的
alternatives.put(Baz.class::isInstance, "toBaz");
但对于大量情况,最好以允许高效查找的方式对谓词进行编码(例如,使用类作为映射键并动态添加遇到的子类)。
请注意,上面的两个示例使用“fallback”作为未满足谓词的情况的值。您只需将其替换为 null
即可获得与问题代码中相同的后备结果。
关于Java 8可选,多个filter和多个map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35065303/