2017-05-02 41 views
5

我想使用Optional的流利api並將兩個Consumer應用於它。如何偷看可選項?

我夢想着這樣的事:

Optional.ofNullable(key) 
    .map(Person::get) 
    .ifPresent(this::printName) 
    .ifPresent(this::printAddress); // not compiling, because ifPresent is void 

如何申請幾個Consumer s到一個Optional,而無需將其存儲在一個臨時變量?

回答

4

你可以使用這個語法:

ofNullable(key) 
    .map(Person::get) 
    .map(x -> {printName(x);return x;}) 
    .map(x -> {printAddress(x);return x;}); 
+3

雖然這個作品,我不認爲使用'map'的副作用是好作風。就我個人而言,我寧願用'ifPresent(x - > {doA(x); doB(x);})' –

+2

@RobinTopper人們有時會這樣做,因爲他們一直試圖自己找到他們問題的答案,但沒有找到一個,一旦他們找到了答案,他們想確保下一個搜索者找到答案。 – Esko

+0

此外,這裏的原因是可選實際上是一個懶惰評估monad(_yes,在Java_中),並且只有在詢問最終值處理內部管道後 - 如果沒有值開始,默認行爲被調用,這可能會取決於用於獲得最終值的方法被調用。 – Esko

6

雖然這可能不是看起來很元,我只是結合了影響到一個lambda並傳遞到ifPresent

ofNullable(key) 
    .map(Person::get) 
    .ifPresent(x -> {printName(x); printAddress(x);}); 

另外,您還可以使用andThen來鏈接多個消費者,但這需要將方法參考投入到Consumer,這也不是很優雅。

ofNullable(key) 
    .map(Person::get) 
    .ifPresent(((Consumer) this::printName).andThen(this::printAddress)); 
+0

我喜歡你,因爲它使得它更明顯* /可讀性實際發生的事情(兩個動作,正在被執行)。 – slartidan

1

也許是這樣的:

Optional.ofNullable(key) 
     .map(Person::get) 
     .ifPresent(combine(this::printAddress, this::printWish)); 

其中combine是:

public <T> Consumer<T> combine(Consumer<T>... cs) { 
    return x -> Stream.of(cs).peek(c -> c.accept(x)).close(); 
} 
+0

這與((Consumer)this :: printName).andThen(this :: printAddress)'非常相似,但我喜歡它的可變參數(允許任意數量的消費者)。 – slartidan

+1

另外,您可以將消費者作爲來自某些外部來源的參數,如果您使用'和Then',則必須拆開包裝消費者並手動建立'和Then'鏈。 –