如何在 Java 函数中适当地组合 Predicate 和 Function?
How to suitably compose Predicate and Function in a Java function?
目的是创建一个可在流过滤器中使用的新谓词:
myCollectionOfElement
.stream()
.filter(
MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1()))
.sorted(MyStaticHelperClass.getOtherSubElement().reversed())
.limit(10)
.collect(Collectors.toList())
getSubElement1OfTheElement()
returnsFunction<E,S>
(E包含一个S属性)
getPredicate1OnSubElement1()
returns 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
灵感来自
// 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)的通用组合函数,因为每个接口的抽象方法的名称都不同(在我的例子中是测试和应用)。
我同意。
总而言之,我真正需要的是两个静态函数,一个将 Predicate 转换为 Function,另一个相反。每个Predicate都会被当作一个Function使用,最后的操作会将组合的Function转换为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;
}
对吗?
如果是这样,是否有兴趣释放函数签名中的边界?
我自己回答问题。
使用 lambda :
value -> predicate.test(function.apply(value));
或者如果你真的 want/have 编写一个组合函数,签名必须是这样的:
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);
目的是创建一个可在流过滤器中使用的新谓词:
myCollectionOfElement
.stream()
.filter(
MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1()))
.sorted(MyStaticHelperClass.getOtherSubElement().reversed())
.limit(10)
.collect(Collectors.toList())
getSubElement1OfTheElement()
returnsFunction<E,S>
(E包含一个S属性)
getPredicate1OnSubElement1()
returns 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
灵感来自
// 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)的通用组合函数,因为每个接口的抽象方法的名称都不同(在我的例子中是测试和应用)。
我同意。
总而言之,我真正需要的是两个静态函数,一个将 Predicate 转换为 Function,另一个相反。每个Predicate都会被当作一个Function使用,最后的操作会将组合的Function转换为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;
}
对吗?
如果是这样,是否有兴趣释放函数签名中的边界?
我自己回答问题。
使用 lambda :
value -> predicate.test(function.apply(value));
或者如果你真的 want/have 编写一个组合函数,签名必须是这样的:
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);