编辑:我的问题在这里得到了解答。总而言之,我对非静态方法引用的使用感到困惑。功能接口和引用方法具有不同数量的参数。
我的问题是comment和接受的答案。
我目前正在阅读关于流减少方法的Java教程(https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html)。在那里,我发现了一段我认为错误的代码,所以我做了一个更简单的代码来确保。
// B.java file
import java.util.*;
public class B
{
public static void main(String[] args)
{
List<Integer> zahlen = new LinkedList<Integer>();
zahlen.add(1);
zahlen.add(2);
zahlen.add(3);
Averager averageCollect = zahlen.stream()
.collect(Averager::new, Averager::addcount, Averager::combine);
System.out.println(averageCollect.average());
}
}
// Averager.java from the official Java tutorial
public class Averager
{
private int total = 0;
private int count = 0;
public double average() {
return count > 0 ? ((double) total)/count : 0;
}
public void addcount(int i) { total += i; count++;}
public void combine(Averager other) {
total += other.total;
count += other.count;
}
}
我认为这不起作用的原因是因为这一行:
Averager averageCollect = zahlen.stream()
.collect(Averager::new, Averager::addcount, Averager::combine);
在Stream.collect
(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer-)的Java文档中,它表示作为第二个参数,需要一个与功能接口BiConsumer
匹配的函数,它具有带两个参数的抽象方法。但Averager.addcount
和Averager.combine
只有一个参数。
我还检查了lambda表达式:
Averager averageCollect = zahlen.stream()
.collect(Averager::new, (a,b) -> a.addcount(b), (a,b) -> a.combine(b));
此代码也有效,作为第二个和第三个参数,我有两个参数的函数。
为什么我上面编写的代码确实有效,即使只给出了一个参数的函数?当我将Averager.addcount
和Averager.combine
更改为包含两个这样的参数时,为什么会出现错误消息?
public void addcount(Averager one, Integer i)
public void combine(Averager one, Averager other)
如果我这样做,我会收到以下错误消息:
B.java:12: error: no suitable method found for collect(Averager::new,Averager::addcount,Averager::combine) .collect(Averager::new, Averager::addcount, Averager::combine); ^ method Stream.collect(Supplier,BiConsumer,BiConsumer) is not applicable (cannot infer type-variable(s) R#1 (argument mismatch; invalid method reference cannot find symbol symbol: method addcount(R#1,Integer) location: class Averager)) method Stream.collect(Collector) is not applicable (cannot infer type-variable(s) R#2,A (actual and formal argument lists differ in length)) where R#1,T,R#2,A are type-variables: R#1 extends Object declared in method collect(Supplier,BiConsumer,BiConsumer) T extends Object declared in interface Stream R#2 extends Object declared in method collect(Collector) A extends Object declared in method collect(Collector) 1 error
请帮助我理解。
答案 0 :(得分:6)
Averager averageCollect = zahlen.stream()
.collect(Averager::new, Averager::addcount, Averager::combine);
这很好。它相当于
Averager averageCollect = zahlen.stream()
.collect(() -> new Averager(),
(myAverager, n) -> myAverager.addcount(n),
(dst, src) -> dst.combine(src))
请记住,每个非静态方法都有一个隐藏的this
参数。在这种情况下,它(正确地)将它绑定到accumulator
和combiner
回调的第一个参数。
它也适用于静态方法,例如:
public static void addcount(Averager a, int i) {
a.total += i;
a.count++;
}
public static void combine(Averager dst, Averager src) {
dst.total += src.total;
dst.count += src.count;
}
希望能让所有人更清楚。
但是没有必要更改代码。