So long as you commit to the map being of type HashMap
, you will not do better than iterating over all the key/value pairs in the map, looking for the maximum value. Such a hash table is organized internally for maximum speed in finding keys by their hash code; the organization is indifferent to the values associated with those keys.
To best solve your problem, you need an inverted index on the values. Since several keys can bear the same value in your original map (assuming it was not a bijection), the inverted index is really a multimap, where any given integral key (taken from the set of those that were your original map values) can be associated with any number of integral values (which were your original map keys).
If your inverted index is of type NavigableMap
, with the value type being a collection of integers, then you can use the NavigableMap#lastEntry()
method to find the pairing of the greatest integral key and its corresponding value. Alternately, if you merely had a SortedMap
in hand, you could still use its SortedMap#lastKey()
method to find the key in question. This assumes that the map is ordered by the natural ordering of integers, from lowest to highest.
The Guava library provides a set of multimap types, of which the TreeMultimap
type exposes a view of type SortedMap
with its TreeMultimap#asMap()
method. I recommend you try using that one first.
If you only need to find this answer once for a given input map, and don't want to bother building the entire inverted index, try the following O(n) solution:
public static <T extends Number & Comparable<? super T>>
Collection<? extends T> keysForMaxValueIn(Map<? extends T, ? extends T> map) {
final int size = map.size();
switch (size) {
case 0:
return Collections.emptySet();
case 1:
return Collections.singleton(map.keySet().iterator().next());
default:
final T max = Collections.max(map.values());
// We know that there will be no duplicates in the original key set.
final Collection<T> keys = new ArrayList<T>(size);
for (Map.Entry<? extends T, ? extends T> entry : map.entrySet())
if (max.equals(entry.getValue()))
keys.add(entry.getKey());
return keys;
}
}