有什么方法可以像Consumers一样简单地使用BiConsumers吗?

Is there any way to use BiConsumers as simply as Consumers?

这只是一个理论问题,没有具体应用。

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

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

void doBigThing(List<A> as, B b) {
  // What to do?
}

如何在保持 b 不变的同时迭代 as 并在 doBigThing 中使用 this::doSmallThing

下面当然不行了

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

以下效果很好,实际上是我每天都在使用的。

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

以下也很有效,但有点棘手。

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

void doBigThing(List<A> as, B b) {
  as.stream()
  .forEach(doSmallThingWithFixedB(b))
}

但是所有这些解决方案都没有 Consumer 案例那么简单。那么 BiConsumer 有什么简单的东西吗?

您想 "bind" 函数参数。不幸的是,在 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);
    }
}

并使用:

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

可能有一些第三方库已经包含了这样的方法。但是,使用显式 lambda 对我来说似乎没问题。你不应该试图用方法引用来表达一切。

BiConsumers 在遍历 Map 条目时使用,例如:

Map<A, B> map = ...;
map.forEach(this::doSomething);

Stream.collect() 也将 BiConsumers 作为参数,但它的使用频率低于映射条目上的迭代。

添加一个方法doSmallThing到 B:

class B {
    public void doSmallThing(A a) {
         YourClass.doSmallThing(a, this); // You may want to inline this.
    }
}

并从 doBigThing:

调用它
void doBigThing(List<A> as, B b) {
    as.stream()
        .forEach(b::doSmallThing);
}