7

我正在寻找 Python 片段的 Java 等价物

max_valued_key = max(str_to_double_map.keys(), key=lambda x: str_to_double_map[x])

我想要像 Collections.max 这样的标准有没有办法通过Comparator 的内联定义
来做到这一点,因为我不想为每个其他比较器再写一个类。

我尝试以下代码失败

depScores = foo();
String dep = Collections.max(depScores.keySet(), new Comparator<String>() {
  @Override
  public int compare(String o1, String o2) {
    return depScores.get(o1).compareTo(depScores.get(o2));
  }
});

depScores 变量无法从比较器中读取。
看起来在 java 内部类中无法从外部访问非最终变量!

提前致谢!

4

2 回答 2

4

只需声明depScores为最终变量。如果由于某种原因不能,请创建指向它的第二个(最终)变量。

局部类只有在它们是 final 时才能捕获变量。


作为(非常)后期的附录,Comparator在 Java 8 中从 lambda 创建自定义是微不足道的:

String dep = Collections.max(
    depScores.keySet(),
    Comparator.comparing(k -> depScores.get(k))
);

k -> depScores.get(k)您可以通过将 lambda 替换为方法引用来获得更简洁的信息depScores::get

对于 lambda 类,捕获局部变量的规则depScore比内部类更灵活:捕获的变量只需要有效地为 final。换句话说,它们必须只分配一次,尽管它们不需要显式标记final

于 2013-11-05T09:25:02.213 回答
4

Java 8 你想要的是(将是)可能的:

Map<String,Double> map…
String maxKey=Collections.max(map.keySet(), (x,y)->Double.compare(map.get(x),map.get(y)));

甚至更短

String maxKey = Collections.max(map.keySet(), Comparator.comparingDouble(map::get));

对于以前的 Java 版本,您必须使用:

String maxKey=Collections.max(map.keySet(), new Comparator<String>(){
    public int compare(String x, String y) {
        return Double.compare(map.get(x),map.get(y));
    }
});

可以通过在调用之前将其分配给最终变量来规避map不存在的问题:final

final Map<String,Double> fmap=map;
String maxKey=Collections.max(map.keySet(), new Comparator<String>(){
    public int compare(String x, String y) {
        return Double.compare(fmap.get(x),fmap.get(y));
    }
});

但我认为更直接、更高效的是以下辅助方法,因为它不需要任何哈希查找:

static <K,V extends Comparable<V>> K keyForHighestValue(Map<K,V> map) {
    V maxValue=Collections.max(map.values());
    for(Map.Entry<K,V> e:map.entrySet()) {
        if(e.getValue()==maxValue) return e.getKey();
    }
    throw new ConcurrentModificationException();
}
于 2013-11-05T09:27:26.947 回答