【发布时间】:2016-01-24 23:39:29
【问题描述】:
编辑:我的问题在这里得到了回答。总而言之,我对非静态方法引用的使用感到困惑。那里的功能接口和引用的方法有不同数量的参数。
回答我的问题的是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: 错误: 没有找到适合收集的方法(Averager::new,Averager::addcount,Averager::combine)
.collect(Averager::new, Averager::addcount, Averager::combine);
^
方法 Stream.collect(Supplier,BiConsumer,BiConsumer) 不适用
(无法推断类型变量 R#1
(参数不匹配;无效的方法引用
找不到标志
符号:方法 addcount(R#1,Integer)
位置:平均类))
方法 Stream.collect(Collector) 不适用
(无法推断类型变量 R#2,A
(实际参数列表和形式参数列表的长度不同))
其中 R#1,T,R#2,A 是类型变量:
R#1 扩展方法 collect(Supplier,BiConsumer,BiConsumer) 中声明的对象
T 扩展接口 Stream 中声明的 Object
R#2 扩展了方法 collect(Collector) 中声明的对象
在方法 collect(Collector) 中声明的扩展对象
1 个错误
请帮助我理解。
【问题讨论】:
-
当前项可以是第一个参数。所以
BiConsumer可以method(a, b)用于static方法或a.method(b)用于实例方法。在你破碎的例子中;你已经通过了一个 instance 方法。 -
另见Oracle’s tutorial “Method References”,特别是。 “方法引用的种类”部分。
标签: java lambda callback java-8 java-stream