以下用于对数组列表进行排序的代码有效:
ArrayList<Edge> edges = g.edges();
edges.sort((Comparator.comparingInt(Edge::getWeight)).thenComparing(e -> e.getU() + e.getV() + e.getWeight()));
在做同样的事情时,另一种方式会导致编译时错误
ArrayList<Edge> edges = g.edges();
edges.sort(Comparator.comparingInt(f -> f.getWeight()).thenComparing(e -> e.getU() + e.getV() + e.getWeight()));
g.edges()
返回边数组列表。
为什么会发生这种情况,第一种方法有效,而第二种方法没有?
edges.sort(Comparator.comparingInt(f -> f.getWeight())
与edges.sort(Comparator.comparingInt(Edge::getWeight))
一样正常,但第一种方法不允许使用.thenComparing(\*lambda exp*\)
而第二种方法允许使用static class Edge {
int u;
int v;
int weight;
int getU() {
return u;
}
int getV() {
return v;
}
int getWeight() {
return weight;
}
Edge(int u, int v, int weight) {
this.u = u;
this.v = v;
this.weight = weight;
}
}
。为什么会这样?
Edge类 -
list_data = [
(237146768, u'43 S LUBEC RD', u'LUBEC', u'ME'),
(455414678, u'PO BOX 41', u'LUBEC', u'ME')
]
context = {'list_data': list_data}
return render(request, 'templatename.html', context}
答案 0 :(得分:1)
如果您阅读错误消息,您会得到一个线索:
Error:(13, 50) java: cannot find symbol
symbol: method getWeight()
location: variable f of type java.lang.Object
所以看起来编译器有一个限制,通过像这样的方法链来推断类型参数。有多种方法可以为编译器提供一些提示:
import java.util.ArrayList;
import java.util.Comparator;
public class Edge {
public int getWeight() {
return 0;
}
public static void main(String[] args) throws InterruptedException {
ArrayList<Edge> edges = null;
// The following will work:
edges.sort(Comparator.<Edge>comparingInt(f -> f.getWeight()).thenComparingInt(f -> f.getWeight()));
edges.sort(Comparator.comparingInt((Edge f) -> f.getWeight()).thenComparingInt(f -> f.getWeight()));
edges.sort(Comparator.comparingInt(Edge::getWeight).thenComparingInt(f -> f.getWeight()));
edges.sort(Comparator.comparingInt(f -> f.getWeight()));
//The following will not:
edges.sort(Comparator.comparingInt(f -> f.getWeight()).thenComparingInt(f -> f.getWeight()));
}
}
答案 1 :(得分:1)
这是<T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
的定义。
您的第一行代码 -
Foo
在Comparator.comparingInt(Edge::getWeight)
上实现功能界面ToIntFunction
,在您的情况下 T
要比较的元素类型并返回Edge
在你的第二行代码中 -
Comparator<Edge>
Comparator.comparingInt(f -> f.getWeight())
的类型未定义,因此编译将失败。相反,您可以将f
的类型转换为Edge,这只会以类似的方式工作:
f
虽然现在编译器可能实际上开始建议用方法引用替换它,这与(1)相同。
注意 :为什么推断(Comparator.comparingInt((Edge f) -> f.getWeight()))
类型为f
的推断在线程Generic type inference not working with method chaining?中解释
答案 2 :(得分:0)
在有效的解决方案中,编译器知道Edge::getWeight
期望Edge,因此推断ToIntFunction<? super T>
是ToIntFunction<Edge>
。
但是,使用lambda,编译器无法推断出类型(因此,它不知道它是Edge并将其视为对象)。
快速解决方案是让编译器知道它是Edge:
edges.sort(Comparator.<Edge>comparingInt(f -> f.getWeight()).thenComparing(e -> e.getU() + e.getV() + e.getWeight()));