I have the following TreeMap
with the given 2 values:
Map<Integer, Integer> map = new TreeMap<>();
// 1 --> 3
// 2 --> 4
I want to get the key which has the max value. I get the max value via:
int max = map.values().stream().max(Integer::compare).get();
// 4
However, I cannot filter the map keys based on this max value. So, how can I get the key of the max value (2)? Or key of the given value in TreeMap
? I used TreeMap
instead of HashMap
so that I can sort the map if needed (maybe not need).
CodePudding user response:
To get the proper key you can use this:
Optional<Map.Entry<Integer,Integer>> entry = map.entrySet().stream().max(Map.Entry.comparingByValue());
System.out.println(entry.get().getKey());
CodePudding user response:
I used
TreeMap
instead ofHashMap
so that I can sort the map if needed (maybe not need).
For that purpose, HashMap
will suffice, you might replace TreeMap
with a HashMap
if you are not utilizing it for anything else.
Firstly, you need to create a stream over the entry set, because you can't access a key when you have only a value.
Terminal operation max()
returns an optional object that will hold entry (if result is present). Method map()
invoked on an optional will transform Optional<Map.Entry<Integer, Integer>>
into Optional<Integer>
.
Method orElseThrow()
in this case will be a better alternative to get()
. Both will throw an exception if optional object will be empty. If according to your logic, value is guaranteed to be present it better specify explicitly with orElseThrow()
that your interntion is to throw an exception when result is not present, because this case is abnormal.
NavigableMap<Integer, Integer> map = new TreeMap<>();
int maxKey = map.entrySet().stream()
.max(Map.Entry.comparingByValue()) // Optional<Map.Entry<Integer, Integer>> - entry
.map(Map.Entry::getKey) // Optional<Integer> - key
.orElseThrow();
Since multiple keys could have the same value, it is possible that max value will be mapped to more than one key. In this case you might want to get a list of these keys:
NavigableMap<Integer, Integer> map = new TreeMap<>();
int maxValue = map.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getValue)
.orElseThrow();
List<Integer> maxValues = map.entrySet().stream()
.filter(entry -> entry.getValue() == maxValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
Sidenote: when you are working with a TreeMap
and don't expect that variable could be assigned with an unsorted implementation of the interface Map
, then use interface NavigableMap
as a type. It'll provide you access to such methods as getFirstEntry()
, getFirstKey()
, higherEntry()
, etc. that will not be available with Map
.
CodePudding user response:
If you use the proper interface, this is extremely easy.
NavigableMap<Integer, Integer> map = new TreeMap<>();
return map.lastEntry().getKey();
More importantly, this is much more efficient than using any Stream at all.