有没有什么方法可以像消费者一样简单地使用BiConsumers?

Oli*_*ire 5 java java-8 method-reference

这只是一个没有具体应用的理论问题.

我有以下方法,我不会碰.它可以(如果可能的话)用作BiConsumer.

void doSmallThing(A a, B b) {
  // do something with a and b.
}

void doBigThing(List<A> as, B b) {
  // What to do?
}
Run Code Online (Sandbox Code Playgroud)

我怎么能反覆as,同时保持b恒定,使用this::doSmallThingdoBigThing

当然以下不起作用.

void doBigThing(List<A> as, B b) {
  as.stream()
  .forEach(this::doSmallThing);
}
Run Code Online (Sandbox Code Playgroud)

以下工作很好,实际上是我每天使用的.

void doBigThing(List<A> as, B b) {
  as.stream()
  .forEach(a -> doSmallThing(a, b));
}
Run Code Online (Sandbox Code Playgroud)

以下也适用,但有点棘手.

Consumer<A> doSmallThingWithFixedB(B b) {
  return (a) -> doSmallThing(a, b);
}

void doBigThing(List<A> as, B b) {
  as.stream()
  .forEach(doSmallThingWithFixedB(b))
}
Run Code Online (Sandbox Code Playgroud)

但所有这些解决方案都不能简化Consumer案例.那么有什么简单的存在BiConsumer吗?

Tag*_*eev 7

你想"绑定"函数参数.不幸的是,在Java 8中没有内置机制来执行此操作(除了绑定对象等实例方法之外this::).您可以doSmallThingWithFixedB像这样概括您的方法:

public class Bind {
    public static <A, B> Consumer<A> bindLast(BiConsumer<A, B> fn, B b) {
        return a -> fn.accept(a, b);
    }

    public static <A, B> Consumer<B> bindFirst(BiConsumer<A, B> fn, A a) {
        return b -> fn.accept(a, b);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用:

void doBigThing(List<A> as, B b) {
  as.stream()
    .forEach(Bind.bindLast(this::doSmallThing, b));
}
Run Code Online (Sandbox Code Playgroud)

可能有一些第三方库已经包含这样的方法.但是使用显式lambda对我来说似乎没问题.您不应该尝试使用方法引用来表达所有内容.

  • Afaik,这是*部分功能应用程序*,而不是currying(所以你不应该把方法命名为"curry ......"而是"绑定...",这是一个不仅更正确的命名,而且对于那些不喜欢的程序员来说也是可以理解的.我知道什么是currying).Currying将是一种方法,如"<A,B>功能<A,消费者<B >>咖喱(BiConsumer <A,B> fn){return a - > b - > fn.accept(a,b); }`; 你可以绑定第一个arg,如`curry(this :: doSomething).apply(a)`... (2认同)