سؤال
أنا أبحث عن طريقة مجموعات Google التي تُرجع النتيجة الأولى لتسلسل الموردين الذين لا يعودون NULL.
كنت أبحث في استخدام teerables.find () ولكن في مسند بلدي ، سأضطر إلى الاتصال بمورد بلدي لمقارنة النتيجة ضد NULL ، ثم يجب أن أتصل بها مرة أخرى بمجرد إعادة طريقة البحث عن المورد.
المحلول
بالنظر إلى تعليقك لتهدئة إجابة Storm (الرغبة في عدم الاتصال 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()
تم تقييمه بتكاسل ، وبالتالي Iterables.find()
الحلقات فوقها ، يمكنك تقييمها فقط بقدر أول غيرnull
-العودة واحدة ، وهذا مرة واحدة فقط.
نصائح أخرى
لقد طلبت كيفية القيام بذلك باستخدام مجموعات 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
}
بدلاً من التعليق - إذا كان هذا هو خطأ المتصل في صفك ، فأرمي غير شرعي أو غير قانوني أو غير قانوني حسب الاقتضاء ؛ إذا لم يكن هذا قد حدث من قبل ، استخدم 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;
}
});
هل تحاول حفظ بعض الخطوط؟ التحسين الوحيد الذي يمكن أن أفكر فيه هو استيراد الاكتشاف الثابت حتى تتمكن من التخلص من "Teerables". كما أن المسند هو فئة داخلية مجهولة ، إذا كنت في حاجة إليها في أكثر من مكان يمكنك إنشاء فصل دراسي وسيبدو ، سيبدو ،
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
حيث المورد predicatefinder هو فئة أخرى.
تحديث: في هذه الحالة ، تجد الطريقة الخاطئة. تحتاج فعليًا إلى وظيفة مخصصة مثل هذه يمكن أن تُرجع قيمتين. إذا كنت تستخدم Commons-Collections ، فيمكنك استخدام DefaultMapentry أو يمكنك ببساطة إرجاع كائن [2] أو خريطة.
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
استبدل DefaultMapentry بقائمة من الحجم 2 أو hashmap بحجم 1 أو مجموعة من الطول 2 :)