Nth highest salary using Java Streams API

anil gola
2 min readJan 19, 2023

--

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:

https://buy.stripe.com/6oE5m2e4d8jZ4OkbII

--

--