This is just a theorical question with no concrete application.
I have the following method which I will not touch. It could (if possible at all) be used as a BiConsumer
.
void doSmallThing(A a, B b) {
// do something with a and b.
}
void doBigThing(List<A> as, B b) {
// What to do?
}
How can I iterate on as
while keeping b
constant and use this::doSmallThing
in doBigThing
?
Of course the following doesn't work.
void doBigThing(List<A> as, B b) {
as.stream()
.forEach(this::doSmallThing);
}
The following works nice and is actually what I use everyday.
void doBigThing(List<A> as, B b) {
as.stream()
.forEach(a -> doSmallThing(a, b));
}
The following also works well, but is a bit more tricky.
Consumer<A> doSmallThingWithFixedB(B b) {
return (a) -> doSmallThing(a, b);
}
void doBigThing(List<A> as, B b) {
as.stream()
.forEach(doSmallThingWithFixedB(b))
}
But all of those solutions don't get the simplicity of the Consumer
case. So is there anything simple that exists for BiConsumer
?
答案 0 :(得分:7)
你想&#34;绑定&#34;函数参数。遗憾的是,在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对我来说似乎没问题。你不应试图用方法参考来表达所有内容。
答案 1 :(得分:1)
在迭代Map条目时使用BiConsumers,例如:
Map<A, B> map = ...;
map.forEach(this::doSomething);
Stream.collect()
也将BiConsumers作为参数,但它的使用频率低于对地图条目的迭代次数。
答案 2 :(得分: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);
}