Prerequisite: One should know how to open streams on Map and how to use sorted by passing Comparator.
Consider the following map as input
Map<String,Integer> map = new HashMap<>();
map.put("anil",1000);
map.put("ankit",1200);
map.put("bhavna",1300);
map.put("james",1400);
map.put("micael",1500);
map.put("tom",1600);
map.put("daniel",1700);
We want to fetch second highest salary with employee name. This can be achieved by below code.
Map.Entry<String,Integer> finalResult = map.entrySet()
.stream()
.sorted(Comparator.comparing(entry -> -entry.getValue())) // minus make it to do in desc order
.toList()
.get(1); // index start from 0
It’s quite simple, we just sort the Map.Entry with value and fetch the second element. But then interviewer will come with the below data and above solution fails.
Map<String,Integer> map2 = new HashMap<>();
map2.put("anil",1000);
map2.put("ankit",1200);
map2.put("bhavna",1200);
map2.put("james",1200);
map2.put("micael",1000);
map2.put("tom",1300);
map2.put("daniel",1300);
Now get(1) will return any random value with either tom or daniel. The trick to solve this issue is to invert the map like below
finalResult = [1000=[micael, anil], 1200=[ankit, james, bhavna], 1300=[daniel, tom]]
This can be achieved with below code.
Map<Integer,List<String>> interimResult =
map2.entrySet()
.stream()
.collect(Collectors.groupingBy(entry ->entry.getValue(),
Collectors.mapping(entry -> entry.getKey(),Collectors.toList())
));
Now we have inverted the map and result will be like below but in random order.
{1200=[ankit, james, bhavna], 1300=[daniel, tom], 1000=[micael, anil]}
Now we just need to sort the map based on keys now. This can be easily done with below line of code.
List<Map.Entry<Integer, List<String>>> finalResult2 = map2.entrySet()
.stream()
.collect(Collectors.groupingBy(entry ->entry.getValue(),
Collectors.mapping(entry -> entry.getKey(),Collectors.toList())
))
.entrySet()
.stream()
.sorted(Comparator.comparing(it -> -it.getKey())) // minus sign for decreasing order
.toList();
Now we just need to put .get(n-1) to find the nth largest salary and their respective employee names.
So, final code will look like
Map.Entry<Integer,List<String>> finalResult2 = map2.entrySet()
.stream()
.collect(Collectors.groupingBy(entry ->entry.getValue(),
Collectors.mapping(entry -> entry.getKey(),Collectors.toList())
))
.entrySet()
.stream()
.sorted(Comparator.comparing(it -> it.getKey()))
.toList()
.get(1);
with result as below
1200=[ankit, james, bhavna]
That’s all from my side.
Find my GitHub link for this code
My youtube channel:
English Playlist: https://youtube.com/playlist?list=PL40GtTTY6_-ksLCcjKcHLALPEq66WHpwO
Hindi Playlist: https://www.youtube.com/playlist?list=PL40GtTTY6_-kB4qcrRLzulRmVtM1Ip4Ij
If you like this blog, please clap and follow our channel. We keep posting interesting topics from Java Ecosystem. Also, you can support our team financially: