2017-04-14 14 views
9

उद्देश्य एक नया विधेय एक धारा फिल्टर में प्रयोग करने योग्य बनाने के लिए है:जावा फ़ंक्शन में पूर्वानुमान और फ़ंक्शन को उचित रूप से लिखने के लिए कैसे करें?

myCollectionOfElement 
.stream() 
.filter(
    MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1())) 
.sorted(MyStaticHelperClass.getOtherSubElement().reversed()) 
.limit(10) 
.collect(Collectors.toList()) 

getSubElement1OfTheElement() रिटर्न Function<E,S> (ई एक एस संपत्ति शामिल है) getPredicate1OnSubElement1() रिटर्न Predicate<S>

मैं स्थिर कार्यों का उपयोग विधि संदर्भ बेनकाब करने के लिए और कार्य करता है। मैं ऐसा इसलिए करता हूं क्योंकि स्ट्रीम वेग टेम्पलेट में कहा जाता है और यह संदर्भ लैम्ब्डा सिंटैक्स और विधि संदर्भ का समर्थन नहीं करता है। मैं सभी संभावित संयोजनों के लिए एक स्थिर कार्य नहीं बनाना चाहता, इसलिए मैं वास्तव में उन्हें संगत करने के लिए चाहता हूं।

उदाहरण के लिए, मैं स्थिर getPredicate1OnElementThatCheckProperty1OnTheSubElement1() नहीं चाहता क्योंकि मैं getSubElement1OfTheElement() और getPredicate1OnSubElement1() लिख सकता हूं।

तो मैं एक लिखें समारोह की जरूरत है:

// returns a new Predicate constructed by applying Predicate predicate on the result of Function function 
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<S> predicate) 

// most intuitive : lambda 
return value -> predicate.test(function.apply(value)); 

// with method references 
return function.andThen(predicate::test)::apply; 
// predicate.compose is not available because Predicate interface doesn't extends Function interface 

से प्रेरित Is there a convenience method to create a Predicate that tests if a field equals a given value?

// step by step with variables 
Function <S,Boolean> predicateFunction = predicate::test; 
// a kind of @FunctionalInterface implicit "conversion" ? Predicate -> Function. 
// is that safe ? 

Function <E,Boolean> composed = function.andThen(predicateFunction::apply); 
return composed::apply; 

संपादित करें: https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

:

यह एक डाली संदर्भ कहा जाता है

// the implementation of my compose can also be this ugly one-liner : 
return ((Function <S,Boolean>)predicate::test).compose(function)::apply; 

तो, हम किसी भी कार्यात्मक इंटरफ़ेस (मेरे मामले में फ़ंक्शन और भविष्यवाणी) लेने वाले जेनेरिक रचना समारोह को कार्यान्वित नहीं कर सकते हैं क्योंकि सार इंटरफ़ेस का नाम प्रत्येक इंटरफ़ेस (परीक्षण और मेरे मामले में लागू) के लिए भिन्न होता है।
मैं इसके साथ ठीक हूं।

निष्कर्ष निकालने के लिए, मुझे वास्तव में दो स्थैतिक कार्यों की आवश्यकता है, जो कि एक कार्य को एक समारोह और विपरीत में परिवर्तित करता है। प्रत्येक भविष्यवाणी को एक समारोह के रूप में उपयोग किया जाएगा और अंतिम ऑपरेशन फ़िल्टर फ़ंक्शन के पैरामीटर प्रकार के साथ मिलान करने के लिए रचनात्मक फ़ंक्शन को भविष्य में परिवर्तित कर देगा।

public static <S> Function<S,Boolean> predicateToFunction(Predicate<S> predicate){ 
    return predicate::test; 
} 
public static <S> Predicate<S> functionToPredicate(Function<S,Boolean> function){ 
    return function::apply; 
} 

वह सही है?
यदि हां, तो फ़ंक्शन हस्ताक्षर में सीमाएं जारी करने में कोई रूचि है?

+0

आप व्याख्या कर सकते हैं कि आप क्या हासिल करने की कोशिश कर रहे हैं? –

+2

जेडीके में यह अंतर्निहित कारण नहीं है क्योंकि यह आमतौर पर लैम्ब्डा को लिखने के लिए सरल है। –

+0

@JacobG। मैंने संदर्भ का वर्णन करने के लिए अपनी पोस्ट संपादित की। – fdelsert

उत्तर

3

मैं अपने खुद के सवालों का जवाब देता हूं।

उपयोग लैम्ब्डा:

value -> predicate.test(function.apply(value)); 

या यदि एक लिखें समारोह लिखने के लिए है, तो आप वास्तव में चाहते हैं /, हस्ताक्षर होना चाहिए की तरह कुछ:

public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate) 
संबंधित मुद्दे

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