2015-10-23 11 views
12

मुझे अक्सर Stream फ़िल्टर करने की आवश्यकता होती है या एक अनुमानित उपयोग का उपयोग करने के लिए जो जांचता है कि किसी दिए गए फ़ील्ड का मान दिया गया है या नहीं।क्या कोई भविष्यवाणी करने के लिए कोई सुविधा तरीका है जो परीक्षण करता है यदि कोई फ़ील्ड किसी दिए गए मान के बराबर है?

कहते हैं, उदाहरण के लिए मैं इस POJO है:

public class A { 
    private Integer field; 

    public A(final Integer field) { 
     this.field = field; 
    } 

    public Integer getField() { 
     return field; 
    } 
} 

और मैं field के मूल्य के आधार फिल्टर करने के लिए वस्तुओं की एक Stream हैं:

final Integer someValue = 42; 
    Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(a -> Objects.equals(a.getField(), someValue)) 
      ... 

की सुविधा विधि वहाँ होगा filter विधि के लिए पूर्वानुमान उत्पन्न करें? मैंने देखा कि Predicate.isEqual है लेकिन यह आवश्यकता के अनुरूप नहीं है।

मैं काफी आसानी से इस तरह एक लिख सकते हैं:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return v -> Objects.equals(value, f.apply(v)); 
} 

और के रूप में उपयोग:

Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(isEqual(A::getField, someValue)) 
      ... 

लेकिन मैं JDK से एक मौजूदा विधि पुन: उपयोग करने यदि संभव हो तो पसंद करेंगे।

+5

मुझे नहीं पता कि मुझे पता है। लेकिन ध्यान दें कि यदि आप जानते हैं कि 'कुछ वैल्यू' शून्य नहीं है, तो एक सरल 'a -> someValue.equals (a.getField()) 'पर्याप्त है। यह 'isEqual (ए :: GetField, someValue) 'से भी बदतर नहीं दिखता है, खासकर यदि मैं मानता हूं कि' ए 'बल्कि' NameOfARealLifeClass' 'है ... – Holger

उत्तर

8

ऐसी कोई बिल्टिन फैक्ट्री विधि नहीं है, जिसे आप आसानी से all usages of Predicate within the JFC देखकर देख सकते हैं और "विधिएं ... जो वापस लौटते हैं" की तलाश में हैं। Predicate के भीतर विधियों के अलावा, केवल Pattern.asPredicate() है जो Predicate देता है।

इससे पहले कि आप इस तरह के फैक्ट्री विधि को लागू करने जा रहे हैं, आपको खुद से पूछना चाहिए कि यह वास्तव में इसके लायक है या नहीं। .filter(a -> Objects.equals(a.getField(), someValue)) में आपकी लैम्ब्डा अभिव्यक्ति को जटिल लग रहा है, Objects.equals का उपयोग करना आवश्यक है, जब आप कम से कम एक तर्क के लिए भविष्यवाणी कर सकते हैं कि यह null है। यहाँ के बाद से, someValuenull कभी नहीं है, तो आप अभिव्यक्ति को आसान बनाने में कर सकते हैं:

final Integer someValue = 42; 
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
    .filter(a -> someValue.equals(a.getField())) 
    … 

आप अभी भी कारखाने विधि को लागू करने और रचनात्मक का उपयोग कर क्या पहले से ही वहाँ है के लिए एक मूल्य जीतना चाहते हैं, तो आप उपयोग कर सकते हैं:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return f.andThen(Predicate.isEqual(value)::test)::apply; 
} 

हालांकि, उत्पादन कोड के लिए, मैं नहीं बल्कि इस तरह एक कार्यान्वयन की सलाह देते हैं:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return value==null? t -> f.apply(t)==null: t -> value.equals(f.apply(t)); 
} 

यह है कि क्या चोर परीक्षण बाहर कारकों प्रत्येक परीक्षण में किए जाने वाले ऑपरेशन को सरल बनाने के लिए stant null है। तो इसे अभी भी Objects.equals की आवश्यकता नहीं है। ध्यान दें कि Predicate.isEqual समान है।

+0

क्या आप कृपया बता सकते हैं कि' value == null ?. .. 'समाधान' ऑब्जेक्ट्सequals' पर बेहतर है? – Roland

+0

@ रोलैंड: जब आप प्रत्येक फ़ंक्शन मूल्यांकन में 'Objects.equals' को कॉल करते हैं, तो आप प्रभावी ढंग से जांच करेंगे कि प्रत्येक फ़ंक्शन मूल्यांकन में 'मान'' शून्य' है, भले ही यह बदलेगा। जाहिर है, प्रभाव सबसे बड़ा होगा * यदि * 'मान'' शून्य 'है, जिसके परिणामस्वरूप फ़ंक्शन 't -> f.apply (t) == null'' Objects.equals' से बहुत सस्ता होगा। चूंकि आप इस तरह की उपयोगिता विधि का उपयोग विभिन्न स्थानों पर बहुत समय से कर सकते हैं, प्रभाव जमा हो जाते हैं।जैसा कि कहा गया है, ['Predicate.isEqual' समान है] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/function/Predicate.java # 114) – Holger

+0

स्पष्टीकरण के लिए धन्यवाद! ओह प्रिय ... यही कारण है कि मैंने मूल्य को पहले स्थान पर निकाला था ... यह सप्ताहांत के लिए समय है। – Roland

संबंधित मुद्दे

 संबंधित मुद्दे