[英]How to suitably compose Predicate and Function in a Java function?
目的是創建一個可在流過濾器中使用的新 Predicate :
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>
我使用靜態函數來公開方法引用和函數。 我這樣做是因為在Velocity 模板中調用了流,並且此上下文不支持 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
靈感來自是否有一種方便的方法來創建一個 Predicate 來測試一個字段是否等於給定值?
// 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;
因此,我們不能使用任何函數接口(在我的例子中是 Function 和 Predicate)來實現一個通用的 compose 函數,因為每個接口的抽象方法的名稱都不同(在我的例子中是 test 和 apply)。
我沒問題。
總而言之,我真正需要的是兩個靜態函數,一個將 Predicate 轉換為 Function,另一個則相反。 每個 Predicate 將用作函數,最終操作將組合函數轉換為 Predicate 以匹配過濾器函數的參數類型。
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;
}
那是對的嗎 ?
如果是這樣,是否有興趣釋放函數簽名中的邊界?
我回答我自己的問題。
使用拉姆達:
value -> predicate.test(function.apply(value));
或者,如果你真的想要/必須編寫一個撰寫函數,簽名必須是這樣的:
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate)
我認為最好的方法是使用Predicate
提供的布爾組合方法: and
, or
, not
。 例如,
private Predicate<String> startsWith(String prefix) {
return s -> s.startsWith(prefix);
}
private Predicate<String> endsWith(String suffix) {
return s -> s.endsWith(suffix);
}
Stream.of("Foo","Fuz","Doo","Fo")
.filter(startsWith("F").and(endsWith("o")))
.forEach(System.out::println);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.