java 如何链接BiFunction?

3okqufwl  于 2023-03-21  发布在  Java
关注(0)|答案(4)|浏览(97)

我想链接BiFunctions,就像下面代码示例中的方法chainWanted一样。
BiFunction将Function作为AndThen的参数。是否可以以某种方式链接BiFunction?
这里的代码无法编译,因为这一点,我不能把BiFunction转换为Function。

import java.util.function.BiFunction;
import java.util.function.Function;

import org.openqa.selenium.remote.RemoteWebDriver;

public class Wf {

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> init = this::init;
    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> wait = this::wait;

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainNow = init
            .andThen(d -> {
                System.out.println("--------------");
                return null;
            });

    BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = init
            .andThen((BiFunction) wait);

    public RemoteWebDriver init(RemoteWebDriver d, WfParams params) {
        System.out.println("init(d, params)");
        return d;
    }

    public RemoteWebDriver wait(RemoteWebDriver d, WfParams params) {
        System.out.println("Wf.wait(d, params)");
        return d;
    }

    public static void main(String[] args) throws Exception {
        new Wf().start();
    }

    private void start() {
        chainNow.apply(null, null);
    }
}
yacmzcpb

yacmzcpb1#

将一个Function链接到另一个Function是很自然的,因为第一个函数的返回值作为参数传递给下一个函数,而该函数的返回值作为参数传递给后续函数,依此类推。但BiFunction不自然,因为它们有两个参数。第一个参数是前一个函数的返回值,但是第二个参数会是什么呢?它还解释了为什么BiFunction允许用andThen链接到一个Function,而不是另一个BiFunction
然而,这表明,如果有某种方法可以提供第二个参数的值,则可以将一个BiFunction链接到另一个BiFunction。这可以通过创建一个帮助函数来完成,该帮助函数将第二个参数的值存储在局部变量中。然后,BiFunction可以通过从环境中捕获该局部变量并将其用作第二个参数来转换为Function
这就是它的样子。

BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = this::chainHelper;

RemoteWebDriver chainHelper(RemoteWebDriver driver, WfParams params) {
    return
        init.andThen(rwd -> wait.apply(rwd, params))
            .apply(driver, params);
}

// ...

chainWanted.apply(driver, params);

chainHelper方法保存params参数以供稍后捕获。我们调用init.andThen()来进行链接。但这需要Function,而waitBiFunction。我们使用lambda表达式而不是使用方法引用this::wait

rwd -> wait.apply(rwd, params)

它从词法环境中捕获params。这给出了一个lambda表达式,该表达式接受一个参数并返回一个值,因此它现在是一个Function,它 Package 了waitwait是一个BiFunction。这是一个 partial applicationcurrying 的示例。最后,我们使用apply()调用结果BiFunction,传递原始参数。

holgip5t

holgip5t2#

调用wait的WfParams应该从哪里来?如果你想在所有函数调用中重用相同的WfParams,只需将WfParams作为类成员变量,而不是将其传递给每个函数。

class Wf {
    private final WfParams params;

    public Wf(WfParams params) {
        this.params = params;
    }

    UnaryOperator<RemoteWebDriver> init = this::init;
    UnaryOperator<RemoteWebDriver> wait = this::wait;

    Function<RemoteWebDriver,RemoteWebDriver> chain = init.andThen(wait);

    RemoteWebDriver init(RemoteWebDriver d) {
        // can use WfParams here
        return d;
    }

    RemoteWebDriver wait(RemoteWebDriver d) {
        // can use WfParams here            
        return d;
    }

    private void start() {
        chain.apply(null);
    }

    public static void main(String[] args) {
        new Wf(new WfParams()).start();
    }   
}

有什么特殊的原因需要像这样使用函数链吗?为什么不简单地从start()调用init(...); wait(...);呢?

rdlzhqv9

rdlzhqv93#

我做了这样的事情-创建了我的自定义BiFunction。想法是:
1.返回类型与第二个参数相同
1.第一个参数在内部传递给链式双函数

public interface BiFunctionCustom<T, U> extends BiFunction<T,U,U> {

  default BiFunctionCustom<T, U> andThen(BiFunctionCustom<T, U> after) {
      Objects.requireNonNull(after);
      return (T t, U u) -> after.apply(t, apply(t, u));
  }
}
68de4m5k

68de4m5k4#

虽然它看起来不像一个普通的链接,但我来到了下面的方法,在概念上类似于斯图尔特马克斯提出的一个:

BiFunction<Param1, Param2, Param1> firstBiFunc = (p1, p2) -> {
    // DO SOME STUFF
    return secondBiFunc.apply(p1, p2);
};
BiFunction<Param1, Param2, Param1> secondBiFunc = (p1, p2) -> {
    // DO SOME STUFF
    return p1
};

相关问题