I was able to accomplish this similarly to Boris' suggested answer. However, any IDE that I used refused to infer the generic types, so I had to explicitly specify them for the first call to Comparator#comparing
as seen below:
Map<String, Integer> map = new LinkedHashMap<>();
map.put("garden", 2);
map.put("road", 4);
map.put("street", 5);
map.put("park", 5);
map.put("highway", 5);
map = map.entrySet()
.stream()
.sorted(Comparator.<Entry<String, Integer>, Integer>comparing(Entry::getValue)
.thenComparing(Comparator.comparing(Entry::getKey)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (k, v) -> {
throw new IllegalStateException(String.format("Duplicate Key: %s", k));
}, LinkedHashMap::new));
System.out.println(map);
The code above yields the following output:
{garden=2, road=4, highway=5, park=5, street=5}
I've noticed that you wish for the values to be in descending order, but the keys which share a value to be in ascending order. Below is that solution (which is nearly identical):
map = map.entrySet()
.stream()
.sorted(Comparator.<Entry<String, Integer>, Integer>comparing(Map.Entry::getValue).reversed()
.thenComparing(Comparator.comparing(Entry::getKey)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (k, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", k));
}, LinkedHashMap::new));
Note: Entry
refers to java.util.Map.Entry
and Collectors
refers to java.util.stream.Collectors
.