在Java方面,我是公平的,我决定稍微深入了解API的实现和使用,特别是Stream。
我做了一个实现,因为我认为我做得对,而且成功了。然而,我意识到有件事困扰着我。
mapMulti函数接受参数BiConsumer:
default <R> Stream<R> mapMulti(BiConsumer<? super T, ? super Consumer<R>> mapper) {
Objects.requireNonNull(mapper);
return flatMap(e -> {
SpinedBuffer<R> buffer = new SpinedBuffer<>();
mapper.accept(e, buffer);
return StreamSupport.stream(buffer.spliterator(), false);
});
}然后,我想通过传递元素类的接受函数来对mapMulti函数进行基准测试(这就是为什么我放弃了s的值,而ExecutionPlan只是拥有要用JMH进行基准测试的值)。
public void mapMultiTest(ExecutionPlan exec){
Stream<Integer> s = exec.elts.stream().mapMulti(Element::accept);
}下面是元素类,它简单地将int分解为素数,并对使用者调用forEach。
public record Element(int value) {
public void accept(Consumer<Integer> consumer) {
decomp().forEach(consumer);
}
public ArrayList<Integer> decomp() {
ArrayList<Integer> list = new ArrayList<>();
int value = this.value;
while (!isPrime(value)) {
int prime = 2;
while (!isPrime(prime) || value % prime != 0)
prime++;
list.add(prime);
value /= prime;
}
list.add(value);
return list;
}
private boolean isPrime(int num) {
if (num <= 1) {
return false;
}
for (int i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
}我的问题是:为什么我的元素::accept(理论上是mapper arg)在它不是BiConsumer类型时被认为是有效的,并且只接受一个参数,即使在mapMulti中调用它时,它接受元素和缓冲区参数。
我可能完全忽略了一些显而易见的东西,或者对这些函数有了错误的理解,但是我在理解BiConsumer, Consumer, Functions, BiFunctions等方面遇到了一些困难。
事先谢谢,我希望我能理解这类我觉得非常有趣的主题,尤其是那些API的开发方式。
发布于 2021-09-03 11:57:45
因此,正如@Thomas ger在评论中指出的那样
Element.accept()是一个实例方法。要调用它,需要两个对象:一个元素实例和一个消费者消费者。方法引用足够聪明,可以检测到这是一个BiConsumer
所以
elts.stream().<Integer>mapMulti((elt,cons)->{
elt.accept(cons);
})和
elts.stream().<Integer>mapMulti(Element::accept)是同一件事
非常感谢!
https://stackoverflow.com/questions/69043025
复制相似问题