Java - built-in comparator definition for Collection.max

I am looking for Java equivalent for python fragment

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

I want something standard, like Collections.max. Is there a way to do this with the built-in comparator definition, since I don't want to write another class for every other comparator.

I unsuccessfully executed the following code

 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)); } }); 
The variable is not read from the comparator.
It seems that in the inner class, java cannot access a variable other than the outer one!

Thanks in advance!

+7
java
source share
2 answers

Just declare depScores as the final variable. If for some reason you cannot create a second (final) variable pointing to it.

Local classes can only capture variables if they are final.


As a (very) late addition, it is trivial to create a custom Comparator from lambda in Java 8:

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

You can become even more concise by replacing the lambda k -> depScores.get(k) with the depScores::get method link.

Rules for capturing local variables, such as depScore , are more flexible for lambda than inner classes: captured variables need only be final. In other words, they should be assigned exactly once, although they should not be explicitly labeled final .

+4
source share

What do you want (will) be possible with Java 8:

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

or even shorter

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

For a previous version of Java, you should use:

 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)); } }); 

Problems with map without being final can be circumvented by assigning it a final variable right before the call:

 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)); } }); 

But I think that the following helper method will be even simpler and more efficient, since it does not require any hash requests:

 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(); } 
+4
source share

All Articles