Search code examples
javadictionaryhashmaplinkedhashmap

How to sort a HashMap by value but keep the order of duplicates?


I'm trying to sort the tableProbability map into a new one called sorted. In tableProbability the values are the following:

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

I have the following code that sorts the Map:

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

But what I end up getting is the following Map:

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

And what I am supposed to get is:

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

Is there any way to retain the duplicate order or at least when it finds a duplicate to put it past the one with the equal value?


Solution

  • Your code works fine, but you can simplify it as follows:

    1. Source map:

      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. This code works fine:

      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. Simplified version:

      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}
      

    See also: Ordering Map<String, Integer> by List<String> using streams