我正在尋找Google Collections方法,該方法返回不返回null的供應商序列的第一個結果。Google Collections供應商和查找
我在尋找使用Iterables.find(),但是在我的Predicate中,我將不得不打電話給我的供應商,將結果與null進行比較,然後在find方法返回供應商後再次調用它。
我正在尋找Google Collections方法,該方法返回不返回null的供應商序列的第一個結果。Google Collections供應商和查找
我在尋找使用Iterables.find(),但是在我的Predicate中,我將不得不打電話給我的供應商,將結果與null進行比較,然後在find方法返回供應商後再次調用它。
數組鑑於您的評論平息風暴的回答更換DefaultMapEntry(不要叫Supplier.get()
的願望兩次) ,那麼怎麼樣:
private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
public X apply(Supplier<X> in) {
// If you will never have a null Supplier, you can skip the test;
// otherwise, null Supplier will be treated same as one that returns null
// from get(), i.e. skipped
return (in == null) ? null : in.get();
}
}
然後
Iterable<Supplier<X>> suppliers = ... wherever this comes from ...
Iterable<X> supplied = Iterables.transform(suppliers, SUPPLY);
X first = Iterables.find(supplied, Predicates.notNull());
注意,ITE來自Iterables.transform()
的rable是懶惰評估的,因此當Iterables.find()
在它上面循環時,你只評估到第一個非null
- 返回一個,而且只有一次。
這是什麼問題?
List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
boolean apply(Supplier supplier) {
return supplier.isSomeMethodCall() == null;
}
boolean equals(Object o) {
return false;
}
});
你想保存一些行嗎?我可以考慮的唯一優化是靜態導入查找,以便您可以擺脫「Iterables」。另外,謂語是一個匿名內部類,如果你需要它在一個以上的地方,你可以創建一個類,它看上去就像這樣,
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
哪裏SupplierPredicateFinder是另一個類。
更新:在這種情況下查找是錯誤的方法。你實際上需要一個像這樣的自定義函數,它可以返回兩個值。如果您使用的是commons-collections,那麼您可以使用DefaultMapEntry,或者您可以簡單地返回Object [2]或Map.Entry。
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
大小爲2的列表或尺寸1的一個HashMap或長度2 :)
在供應商(Google Collections)界面上有一個名爲get()的方法。這是一個耗時的計算。 Iterables.find在謂詞匹配時返回供應商,而不是get()的結果。所以在find()的結果之後,我需要再次調用get,這將需要再次執行計算。我可以使用MemoizingSupplier,但如果find方法返回供應商的結果而不是供應商自己,結果會更好。 – pledge 2010-02-19 11:54:17
用更多代碼示例更新了答案! – 2010-02-19 13:57:05
這個答案是不連貫的。根據原問題的內容,上半場無效。在下半年,當用戶只需要重對象時,爲什麼要返回供應商和重對象?我很困擾我們會很快向任何人推薦Map.Entry/Object [2]黑客(而且這是一種怪誕的黑客攻擊),除非真的需要。 – 2010-02-19 17:10:38
您問過如何使用Google收藏集來做到這一點,但您可以在不使用Google收藏集的情況下這樣做。將它與Cowan的答案(這是一個很好的答案)相比較 - 這更容易理解?
private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
for (Supplier<Thing> supplier : thingSuppliers) {
Thing thing = supplier.get();
if (thing != null) {
return thing;
}
}
// throw exception or return null
}
在註釋中的 - 如果這是你的類的調用者的過錯,拋出IllegalArgumentException或IllegalStateException異常適當的;如果這不應該發生,請使用AssertionError;如果這是一個正常的事件,那麼調用它的代碼需要檢查,你可能會返回null。
這是我原來的解決方案,我應該真的在問題中發佈它。然而,正如我們已經發現Predicates和Functions的一些很好的用法,我正在尋找是否存在像Suppliers.firstSupplied這樣的東西。正如Cowan的(工作)建議所顯示的,這可能是Java中的功能風格導致代碼難以理解的情況。測試通過這兩種解決方案。 – pledge 2010-02-19 19:29:18
+1用於回答所問的問題。不過,我認爲所問的問題應該是「這樣做的最佳方式是什麼」,而不是「使用谷歌收藏的方法是什麼」,所以我提供了另一個答案。 – 2010-02-19 17:23:48
這確實對我有用。 – pledge 2010-02-19 19:18:05
你應該接受這個答案。 – harschware 2010-02-22 19:21:55