你已經看到過很多次自己,那我敢肯定:有沒有一種優雅的方式來獲得Java中的多個方法返回的第一個非null值?
public SomeObject findSomeObject(Arguments args) {
SomeObject so = queryFirstSource(args); // the most likely source first, hopefully
if (so != null) return so;
so = querySecondSource(args); // a source less likely than the first, hopefully
if (so != null) return so;
so = queryThirdSource(args); // a source less likely than the previous, hopefully
if (so != null) return so;
// and so on
}
我們有不同的來源,我們搜索的對象可以是。作爲一個更生動的例子,我們可以想象,我們首先檢查用戶標識是否在特權用戶列表中。如果不是,我們檢查用戶標識是否在允許的用戶列表中。否則我們返回null。 (這是不是最好的例子,但我希望這是一個生動的,足以之一。)
Guava我們提供了一些助手,可以美化上面代碼:
public SomeObject findSomeObject(Arguments args) {
// if there are only two objects
return com.google.common.base.Objects.firstNonNull(queryFirstSource(args), querySecondSource(args));
// or else
return com.google.common.collect.Iterables.find(
Arrays.asList(
queryFirstSource(args)
, querySecondSource(args)
, queryThirdSource(args)
// , ...
)
, com.google.common.base.Predicates.notNull()
);
}
但是,隨着更多的經驗中我們將有已經看到,如果查找(即queryXXXXSource(args)
)需要一定的時間,這可能會表現不佳。這是因爲我們現在先查詢所有來源,然後將結果傳遞給在null
之外的結果中找到第一個的方法。
與第一個例子相反,在第一個例子中,只有當前者不返回某些東西時才評估下一個數據源,這個第二個解決方案起初看起來可能更好,但可能會更糟糕。
這裏是我們談到我的實際問題的地方,以及我建議的一些事情,我希望有人已經實施了它的基礎,或者有人可能會提出一個甚至是聰明的解決方案。
用簡單的英語:已經有人已經實施了類似這樣的defferedFirstNonNull
(見下文)的東西?有沒有一個簡單的Java解決方案來實現這個新的Stream框架?你能否提出另一個可以達到相同結果的優雅解決方案?
規則:的Java 8被允許以及積極維護和知名第三方庫像谷歌的番石榴或Apache許可證或類似Apache的共享郎(沒有GPL!)。
提出的解決方案:
public SomeObject findSomeObject(Arguments args) {
return Helper.deferredFirstNonNull(
Arrays.asList(
args -> queryFirstSource(args)
, args -> querySourceSource(args)
, args -> queryThirdSource(args)
)
, x -> x != null
)
}
因此該方法defferedFirstNonNull
將陸續評估每個lambda表達式,並儘快作謂語(x -> x != null
)是真實的(即我們找到了一個匹配)的方法將返回結果立即並不會查詢任何進一步的來源。
PS:我知道表達式args -> queryXXXXSource(args)
可以縮短爲queryXXXXSource
。但是這會使提出的解決方案難以閱讀,因爲一見鍾情並不明顯。
我選擇了這個答案作爲我指定的答案,因爲它結合了所有其他答案,因此似乎'完整'。我不知道'Optional <>'類,我認爲它爲我的問題提供了最優雅的方式。 – cimnine 2014-10-02 14:43:52