【问题标题】:How to suitably compose Predicate and Function in a Java function?如何在 Java 函数中适当地组合谓词和函数?
【发布时间】:2017-04-14 16:02:16
【问题描述】:

目的是创建一个可在流过滤器中使用的新谓词:

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

所以我需要一个 compose 函数:

// 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;

因此,我们无法实现采用任何功能接口(在我的情况下为 Function 和 Predicate)的通用 compose 函数,因为每个接口的抽象方法的名称不同(在我的情况下为 test 和 apply)。
我没问题。

总之,我真正需要的是两个静态函数,一个将 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;
}

对吗?
如果是这样,是否有兴趣释放函数签名中的边界?

【问题讨论】:

  • 你能解释一下你想要达到的目标吗?
  • JDK 没有内置这个的原因是因为通常只显式地编写 lambda 比较简单。
  • @JacobG。我编辑了我的帖子来描述上下文。
  • 建造者模式怎么样?
  • @Antoniossss 你的意思是一个新的流利的类,一个一个,一个谓词还是一个函数?检查类型并将它们全部组合起来?它似乎比我的需要更雄心勃勃,但可能很有趣。我只想验证我的 compose 函数是否正确并且在所有情况下都有效。

标签: java lambda java-8 method-reference functional-interface


【解决方案1】:

我自己回答问题。

使用 lambda:

value -> predicate.test(function.apply(value));

或者如果你真的想/必须写一个 compose 函数,签名必须是这样的:

public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate)

【讨论】:

    【解决方案2】:

    我认为最好的方法是使用布尔组合方法Predicate 提供:andornot。例如,

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

    【讨论】:

      猜你喜欢
      • 2018-07-01
      • 2011-03-12
      • 2021-01-23
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 2019-03-15
      • 1970-01-01
      相关资源
      最近更新 更多