How to define custom sorted comparator in java 8 Stream to compare on the key and the value

Declare the Comparator using thenComparing for chaining.

Comparator<Map.Entry<Integer, Integer>> entryComparator
            = Map.Entry.<Integer, Integer>comparingByValue(Comparator.reverseOrder())
                                         .thenComparing(Map.Entry.comparingByKey());

Map<Integer,Integer> ranks = Map.of(2, 6, 5, 13, 1, 11, 3, 13, 9, 22);

List<Integer> ranksList= ranks.entrySet().stream()
            .sorted(entryComparator)
            .map(Map.Entry::getKey).limit(47)
            .collect(Collectors.toList());

System.out.println(ranksList);

Output is the desired:

[9, 3, 5, 1, 2]

The type specification <Integer, Integer> of comparingByValue is necessary for Java to infer the types for Map.Entry.comparingByKey().


You are looking for a custom Comparator such as this:

.sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue()) == 0 ?
        o1.getKey().compareTo(o2.getKey()) : o2.getValue().compareTo(o1.getValue()))

Theoretically,

  • compare the values first in descending order o2.getValue().compareTo(o1.getValue()) and

  • if they are equal compare the keys in the ascending order o1.getKey().compareTo(o2.getKey()).