Сортировка карты в порядке убывания на основе значения и сортировка ключа в порядке возрастания, если значение дублируется

avatar
vivek modi
8 августа 2021 в 16:34
586
2
0

Я использую интерфейс карты для чтения из файла, а затем сохраняю значения в нем как пару "ключ-значение".

Map<String, Integer> map = new HashMap<>();

Значение

A 25
D 10
B 15
E 15
C 17

Я хочу сначала отсортировать по значению в порядке убывания Сортировка карты<Key,Value> в порядке убывания на основе значения. Это поможет добиться порядка в порядке убывания. Но если значение дублируется, я хочу отсортировать по ключу в порядке возрастания.

Ожидаемый результат

A 25
C 17
B 15
E 15
D 10

Кто-нибудь знает, как этого добиться.

Источник

Ответы (2)

avatar
Unmitigated
8 августа 2021 в 16:42
1

Вы можете использовать Comparator.comparing и thenComparing для сортировки в правильном порядке. Потоки можно использовать для сортировки и сбора новых Map в LinkedHashMap для сохранения нового порядка.

Map<String, Integer> map = Map.of("A", 25, "D", 10, "B", 15, "E", 15, "C", 17);
Map<String, Integer> result = map.entrySet().stream()
    .sorted(Comparator.<Map.Entry<String, Integer>>comparingInt(Map.Entry::getValue)
       .reversed().thenComparing(Map.Entry::getKey))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, 
         (a,b)->b, LinkedHashMap::new));
System.out.println(result);

Демо

vivek modi
8 августа 2021 в 16:48
0

можете ли вы объяснить мне .sorted(Comparator.<Map.Entry<String, Integer>>comparingInt(Map.Entry::getValue) .reversed().thenComparing(Map.Entry::getKey)) эта часть

vivek modi
8 августа 2021 в 16:48
0

также эта часть .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a,b)->b, LinkedHashMap::new))

Unmitigated
8 августа 2021 в 16:53
0

@vivekmodi Comparator.comparingInt используется здесь для сортировки по значению каждой записи, и мы вызываем reversed для получения убывающего порядка (по возрастанию по умолчанию). thenComparing используется для сортировки ключей в порядке возрастания, если значения совпадают. Collectors.toMap здесь просто преобразует поток записей в LinkedHashMap. См. документацию для более подробной информации.

avatar
Eritrean
8 августа 2021 в 17:11
1

В качестве альтернативы принятому ответу я бы извлек компараторы, которые ИМО делает его более читаемым, то есть что-то вроде:

Map<String, Integer> map = Map.of("A", 25, "D", 10, "B", 15, "E", 15, "C", 17);

Comparator<Map.Entry<String,Integer>> byValueDesc = Map.Entry.comparingByValue(Comparator.reverseOrder());
Comparator<Map.Entry<String,Integer>> byKeyAsc = Map.Entry.comparingByKey();

Map<String, Integer> result =

    map.entrySet()
            .stream()
            .sorted(byValueDesc.thenComparing(byKeyAsc))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2)->e1, LinkedHashMap::new));