简体   繁体   English

如何在 Java 函数中适当地组合 Predicate 和 Function?

[英]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.

相关问题 Java 8,如何从(Bi)谓词组成(Bi)函数 - Java 8, how to compose (Bi)Function from (Bi)Predicate 在Java 8中结合函数和谓词 - Combine a Function and a Predicate in Java 8 Java 8 - 如何使用带参数函数的谓词? - Java 8 - How to use predicate that has a function with parameter? 如何将 java.util.function.Predicate 实现为 Kotlin lambda? - How to implement a java.util.function.Predicate as Kotlin lambda? Java8:如何用函数谓词替换按位包含和(&)? - Java8: How to replace the bitwise inclusive and ( &) by the function Predicate? 如何使用谓词 function 过滤 Java 中的列表? - How can I filter a list in Java using a predicate function? 带有谓词对象的Java 8流中的动态函数调用 - Dynamic function calling in Java 8 Streams with Predicate Object Java 8谓词泛型函数不接受整数列表 - Java 8 predicate generic function is not accepting List of Integers 无法访问 java.util.function.Predicate - Cannot access java.util.function.Predicate 如何解决问题:“java:不兼容的类型:...项目无法转换为 java.util.function.Predicate<!--? super ...Project--> “? - How to solve the issue: "java: incompatible types: ...Project cannot be converted to java.util.function.Predicate<? super ...Project>"?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM