[英]Java 8 Optional, multiple filter and multiple map
我想使用Java 8,如何在Java 8 Optional中使命令式樣式變為功能樣式?
例如,假設exchange.getIn()。getBody()可能為null或不為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");
我的問題是地圖已經是String,所以我無法將其設為一個內襯:
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
以獲得與問題代碼相同的后備結果。
為了使您的一線工作,我將邏輯“轉”為類似以下內容:
Object body = exchange.getIn().getBody();
Stream.of(
new Pair<Class, String>(Foo.class, "toFoo"),
new Pair<Class, String>(Bar.class, "toBar"))
.filter(pair -> body != null && body.getClass().isAssignableFrom(pair.getKey())))
.findFirst()
.map(Pair::getValue)
.orElse("default");
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.