7

I have the following HashMap:

HashMap<String, Integer> counts = new HashMap<String, Integer>();

What is the simplest way to order it according to the values?

spongebob
  • 8,370
  • 15
  • 50
  • 83
Anasaw
  • 119
  • 1
  • 7
  • 1
    You cannot sort a HashMap, you can use a TreeMap but keys and values must be the other way around for your requirement. – Bhesh Gurung Oct 16 '12 at 16:54
  • Please ignore the recommendation in my previous comment. The problem with that is that there will be always a chance that multiple entries with same count, and the map doesn't allow duplicate keys. I think the best is to follow the answers with the suggestions in on sorting the list of entries. – Bhesh Gurung Oct 16 '12 at 17:19
  • If you are not restricted to using a `HashMap`, why not create a class which contains your word as a `String`, your count as an `int`, and and have it implement Comparable to find a max value, then just insert all of these objects into a maximum heap, and find the root node of the heap? – Zéychin Oct 16 '12 at 17:23

4 Answers4

9

You can't sort a Map by the values, especially not a HashMap, which can't be sorted at all.

Instead, you can sort the entries:

List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
  public int compare(
      Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) {
    return entry1.getValue().compareTo(entry2.getValue());
  }
});

will sort the entries in ascending order of count.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
4

You can get a set of entries (Set of Map.Entry) from a map, by using map.entrySet(). Just iterate over them, and check the values by getValue().

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
1

A work around, if you want to them print them in order(Not storing).

  1. Create a new Map (tempMap) and put your value as key and key as value. To make the keys unique, please add some unique value in each of the keys e.g. key1 = value1+@0.

  2. Get the list of values as map.values() as list myVlues

  3. Sort the myVlues list as Collections.sort(myVlues)

  4. Now iterate the myVlues, get the corresponding key from tempMap, restore the key e.g. key.substring(0, key.length-2) and print the key and value pair.

Hope this helps.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
1

A TreeMap can keep its entries in an order defined by a Comparator.

  1. We can create a comparator that will order the Map by putting the greatest value first.
  2. Then, we will build a TreeMap that uses that Comparator.
  3. We will then put all the entries in our counts map into the Comparator.
  4. Finally, we will get the first key in the map, which should be the most common word (or at least one of them, if multiple words have equal counts).

    public class Testing {
        public static void main(String[] args) {
    
            HashMap<String,Double> counts = new HashMap<String,Integer>();
    
            // Sample word counts
            counts.put("the", 100);
            counts.put("pineapple",5);
            counts.put("a", 50);
    
            // Step 1: Create a Comparator that order by value with greatest value first
            MostCommonValueFirst mostCommonValueFirst =  new MostCommonValueFirst(counts);
    
            // Step 2: Build a TreeMap that uses that Comparator
            TreeMap<String,Double> sortedMap = new TreeMap<String,Integer (mostCommonValueFirst);
    
            // Step 3: Populate TreeMap with values from the counts map
            sortedMap.putAll(counts);
    
            // Step 4: The first key in the map is the most commonly used word
            System.out.println("Most common word: " + sortedMap.firstKey());
        }
    }
    
    private class MostCommonValueFirst implements Comparator<String> {
       Map<String, Integer> base;
    
       public MostCommonValueFirst(Map<String, Integer> base) {
          this.base = base;
       }
    
       // Note: this comparator imposes orderings that are inconsistent with equals.    
       public int compare(String a, String b) {
          if (base.get(a) >= base.get(b)) {
              return 1;
          } else {
             return -1;
          } // returning 0 would merge keys
       }
     }
    

Source: https://stackoverflow.com/a/1283722/284685

Community
  • 1
  • 1
Adam
  • 43,763
  • 16
  • 104
  • 144
  • I'm not sure if this is a good idea. The key's comparator order can change with the values of the map. It's essentially a mutable key (as far as `TreeMap` is concerned). – Steve Kuo Oct 16 '12 at 17:20
  • Agreed, but we can still do it after we are done populating the map. – Adam Oct 16 '12 at 17:21