我想使用包含每个项目值的地图对列表进行排序。
Map<Integer, Float> map = new HashMap<>();
List<Integer> list = new ArrayList<>();
map.put(0, 0.0f);
map.put(1, 5.0f);
map.put(2, 2.0f);
list = new ArrayList<>(map.keySet());
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer left, Integer right) {
Float leftCost = map.get(left);
Float rightCost = map.get(right);
return leftCost.compareTo(rightCost);
}
})
我希望订单为0,2,1
,因为1
的值高于2
。但是java不要让我这样做。我收到以下错误:Cannot refer to a non-final variable map inside an inner class defined in a different method
我怎么能这样做呢?
答案 0 :(得分:6)
最后决定:
final Map<Integer, Float> map = new HashMap<Integer, Float>();
List<Integer> list = new ArrayList<Integer>(); // this assignment is unncessary [1]
map.put(0, 0.0f);
map.put(1, 5.0f);
map.put(2, 2.0f);
list = new ArrayList<Integer>(map.keySet()); // 1. assignment is replaced here
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer left, Integer right) {
Float leftCost = map.get(left);
Float rightCost = map.get(right);
return leftCost.compareTo(rightCost);
}
})
由于你的地图是可变的,你仍然可以修改它。
答案 1 :(得分:2)
一个匿名内部类(您的比较器是一个)只能引用声明为final
的局部变量,以便访问您的地图 - 您必须将其声明为final
。
请注意,声明为final
并不会阻止您修改地图对象,您无法将新对象分配给变量map
。
答案 2 :(得分:1)
您的Comparator
是一个匿名内部类。在其中,您正在尝试访问在包含匿名内部类的方法中声明的局部变量map
。
Java中存在一个限制,即只有局部变量为final
时才能执行此操作。因此,请设置变量map
final
:
final Map<Integer, Float> map = new HashMap<>();
答案 3 :(得分:1)
在您的情况下,解决方案很简单:将地图标记为final
:
final Map<Integer, Float> map = new HashMap<>();
您可能对单词final
感到困惑。它不会限制您对地图的操作。它只是不允许您在您的情况下更改对映射的引用。
此要求的原因是您的比较器是匿名内部类。所有外部方法变量都复制到匿名类中,因此如果在外部方法中更改它们将产生冲突。这就是编译器要求将从匿名类访问的变量标记为final的原因。
其他解决方案是将比较器提取为单独的类,并将映射作为参数构造函数发送给它。
答案 4 :(得分:0)
你绝对可以做到这一点。只需创建一个命名类来代替扩展Comparator
的匿名类,并将Map
变量作为参数传递。像这样:
@Test
public void test() {
Map<Integer, Float> map = new HashMap<Integer, Float>();
map.put(0, 0.0f);
map.put(1, 5.0f);
map.put(2, 2.0f);
List<Integer> list = new ArrayList<Integer>(map.keySet());
Collections.sort(list, new FloatComparator(map));
System.out.println(list);
}
class FloatComparator implements Comparator<Integer> {
private Map<Integer, Float> mapRef;
public FloatComparator(Map<Integer, Float> newMap) {
mapRef = newMap;
}
@Override
public int compare(Integer left, Integer right) {
Float leftCost = mapRef.get(left);
Float rightCost = mapRef.get(right);
return leftCost.compareTo(rightCost);
}
}
打印出来:
[0, 2, 1]
还可以使您的代码更清晰,IMO。