[英]How to suitably compose Predicate and Function in a Java function?
The purpose is to create a new Predicate usable in a stream filter :目的是创建一个可在流过滤器中使用的新 Predicate :
myCollectionOfElement
.stream()
.filter(
MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1()))
.sorted(MyStaticHelperClass.getOtherSubElement().reversed())
.limit(10)
.collect(Collectors.toList())
getSubElement1OfTheElement()
returns Function<E,S>
(E contains a S property) getPredicate1OnSubElement1()
returns Predicate<S>
getSubElement1OfTheElement()
返回Function<E,S>
(E 包含 S 属性) getPredicate1OnSubElement1()
返回Predicate<S>
I use static functions to expose method references and functions.我使用静态函数来公开方法引用和函数。 I do this because the stream is called in a Velocity template and this context doesn't support lambda syntax and method reference .
我这样做是因为在Velocity 模板中调用了流,并且此上下文不支持 lambda 语法和方法引用。 I don't want to create a static function for all possible combinaisons, so I really want them to be composable .
我不想为所有可能的组合创建一个静态函数,所以我真的希望它们是可组合的。
For example here, I don't want to have a static getPredicate1OnElementThatCheckProperty1OnTheSubElement1()
because I can compose getSubElement1OfTheElement()
and getPredicate1OnSubElement1()
.例如在这里,我不想有一个静态的
getPredicate1OnElementThatCheckProperty1OnTheSubElement1()
因为我可以组合getSubElement1OfTheElement()
和getPredicate1OnSubElement1()
。
So I need a compose function :所以我需要一个撰写功能:
// 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
inspired by Is there a convenience method to create a Predicate that tests if a field equals a given value?灵感来自是否有一种方便的方法来创建一个 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;
Edit :编辑 :
It's called a cast context : https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html它被称为转换上下文: 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;
So, we cannot implement a generic compose function taking any functional interface (in my case Function and Predicate) because the name of the abstract method differs for each interface (test and apply in my case).因此,我们不能使用任何函数接口(在我的例子中是 Function 和 Predicate)来实现一个通用的 compose 函数,因为每个接口的抽象方法的名称都不同(在我的例子中是 test 和 apply)。
I'm OK with that.我没问题。
To conclude, what I really need is two static functions, one that converts a Predicate to a Function and the opposite.总而言之,我真正需要的是两个静态函数,一个将 Predicate 转换为 Function,另一个则相反。 Every Predicate will be used as a Function and the final operation will convert the composed Function to Predicate in order to match with the parameter type of the filter 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;
}
Is that correct ?那是对的吗 ?
If so, is there any interest in releasing the bounds in the function signature ?如果是这样,是否有兴趣释放函数签名中的边界?
I answer my own questions.我回答我自己的问题。
Use lambda :使用拉姆达:
value -> predicate.test(function.apply(value));
Or if you really want/have to write a compose function, signature must be something like :或者,如果你真的想要/必须编写一个撰写函数,签名必须是这样的:
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate)
I think the best approach would be use the boolean compose methods Predicate
provides: and
, or
, not
.我认为最好的方法是使用
Predicate
提供的布尔组合方法: and
, or
, not
。 eg,例如,
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.