2017-04-14 23 views
9

的目的是創造在流過濾器一起使用的新的謂詞:如何在Java函數中合適地組成謂詞和函數?

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

getSubElement1OfTheElement()返回Function<E,S>(E含在S屬性) getPredicate1OnSubElement1()返回Predicate<S>

我使用靜態函數,以暴露方法的引用和功能。 我這樣做是因爲該流在速度模板中調用,並且此上下文不支持lambda語法和方法參考我不想爲所有可能的組合創建一個靜態函數,所以我真的希望它們是可組合的

例如,在這裏,我不想有一個靜態的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

JDK沒有內置這個功能的原因是因爲只是明確寫入lambda通常比較簡單。 –

+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)