Как отсортировать HashMap по значению, но сохранить порядок дубликатов?

Я пытаюсь отсортировать карту tableProbability в новую под названием sorted. В tableProbability значения следующие:

Key Value
M 0.1
U 0.3
L 0.3
T 0.2
I 0.1

У меня есть следующий код, который сортирует Map:

LinkedHashMap<Character, Double> sorted = new LinkedHashMap<>();
tableProbability.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        .forEachOrdered(x -> sorted.put(x.getKey(), x.getValue()));

Но в итоге я получаю следующее Map:

Key Value
L 0.3
U 0.3
T 0.2
I 0.1
M 0.1

И что я должен получить:

Key Value
U 0.3
L 0.3
T 0.2
M 0.1
I 0.1

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


person David Trpcevski    schedule 07.01.2021    source источник


Ответы (3)


Ваш код работает нормально, но вы можете упростить его следующим образом:

  1. Исходная карта:

    LinkedHashMap<Character, Double> tableProbability =
            new LinkedHashMap<>() {{
                put('M', 0.1);
                put('U', 0.3);
                put('L', 0.3);
                put('T', 0.2);
                put('I', 0.1);
            }};
    
    System.out.println(tableProbability);
    // {M=0.1, U=0.3, L=0.3, T=0.2, I=0.1}
    
  2. Этот код работает нормально:

    LinkedHashMap<Character, Double> sorted = new LinkedHashMap<>();
    tableProbability.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .forEachOrdered(x -> sorted.put(x.getKey(), x.getValue()));
    
    System.out.println(sorted);
    // {U=0.3, L=0.3, T=0.2, M=0.1, I=0.1}
    
  3. Упрощенная версия:

    LinkedHashMap<Character, Double> sorted2 = tableProbability
            .entrySet().stream()
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .collect(LinkedHashMap::new,
                    (col, e) -> col.put(e.getKey(), e.getValue()),
                    HashMap::putAll);
    
    System.out.println(sorted2);
    // {U=0.3, L=0.3, T=0.2, M=0.1, I=0.1}
    

См. также: Упорядочивание Map‹String, Integer› по списку‹String› с использованием потоков

person Community    schedule 22.01.2021

Вы можете сделать это таким образом. Это обычная операция. Если вы хотите вернуть TreeMap, вы можете указать это ниже. И обычно присваивается типу интерфейса. Для TreeMap это будет NavigableMap.

Map<Character, Double> sorted =
        tableProbability.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(
                        Comparator.reverseOrder()))
                .collect(Collectors.toMap(Entry::getKey,
                        Entry::getValue,
                        (a,b)->a, // merge, not used here but
                                  // syntactically required
                        LinkedHashMap::new // type of map to return
                        ));
person WJS    schedule 07.01.2021

Используйте составной компаратор:

.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())
    .andThen(Map.Entry.comparingByKey())
)
    
person Bohemian♦    schedule 23.01.2021