题
我在寻找一个谷歌集合方法返回不返回null供应商序列的第一个结果。
我看用Iterables.find(),但在我谓我会打电话给我的供应商,结果对空比较,然后再次调用一次find方法返回的供应商。
解决方案
由于您的评论平息风暴的回答(欲望不叫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());
请注意自带Iterables.transform()
出了Iterable是惰性计算,因此作为Iterables.find()
循环过它,你只能尽可能评价作为第一个非null
返流一个,而且只有一次。
其他提示
您问如何做到这一点使用谷歌集合,但这里是你会怎么做,而不使用谷歌集合。它比较考恩的回答(这是一个很好的答案) - 这是比较容易理解。
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。
什么是错的呢?
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是另一个类。
更新:在这种情况下发现是错误的方法。实际上,你需要这样的自定义功能,可以返回两个值。如果使用的是公共的集合则可以使用一个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的散列映射或长度为2的数组替换DefaultMapEntry:)