5

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

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

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

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

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

当然,以下不起作用。

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吗?

4

3 回答 3

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

并使用:

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

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

于 2015-06-25T10:16:59.083 回答
1

BiConsumers 在迭代 Map 条目时使用,例如:

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

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

于 2015-06-25T10:18:16.007 回答
0

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);
}
于 2015-06-25T11:29:34.487 回答