Как определить пользовательский отсортированный компаратор в java 8 Stream для сравнения по ключу и значению - PullRequest
7 голосов
/ 29 октября 2019

Я хочу отсортировать карту с помощью потоков Java 8 и вернуть список ее ключей.

Подпись карты:

Map<Integer, Integer> ranks = new HashMap<Integer, Integer>();

, и данные будут выглядеть как [1 = 6, 5 = 13, 2 = 11]

Есть два условия, при которых я должен отсортировать и вернуть список ключей.

  1. Если все значенияключи различаются, затем сортируйте и возвращайте значения на основе списка в порядке убывания, например,

    input [1=6 , 5=13 , 2= 11 , 4 = 14 ]
    result [4,5,2,1]
    
  2. Если два или более значения ключа имеют одинаковый ранг, то возвращают эти одинаковые значения вв порядке возрастания, а остальная часть элемента в порядке убывания их значений, например

    input [2=6 , 5=13 , 1= 11 , 3=13 ,9 = 22 ] result [9,3,5,1,2]
    

Ниже приведен фрагмент кода, который работает нормально для условия 1, ноне для условия 2.

List<Integer> ranksList = ranks.entrySet().stream()
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
    .map(Map.Entry::getKey)
    .limit(k)
    .collect(Collectors.toList());

Ответы [ 2 ]

6 голосов
/ 29 октября 2019

Объявите Comparator, используя thenComparing для цепочки.

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);

Требуется вывод:

[9, 3, 5, 1, 2]

Спецификация типа <Integer, Integer> из comparingByValue необходима для того, чтобы Java выводила типы для Map.Entry.comparingByKey().

3 голосов
/ 29 октября 2019

Вы ищете пользовательский Comparator, такой как:

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

Теоретически,

  • сначала сравните значения в порядке убывания o2.getValue().compareTo(o1.getValue()) и

  • если они равны сравнить ключи в порядке возрастания o1.getKey().compareTo(o2.getKey()).

...