8

I am trying to figure out how could I get the top 10 values from the HashMap. I was initially trying to use the TreeMap and have it sort by value and then take the first 10 values however it seems that that is not the option, as TreeMap sorts by key.

I want to still be able to know which keys have the highest values, the K, V of the map are String, Integer.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Tohmas
  • 547
  • 2
  • 7
  • 14
  • 4
    what do you mean the top 10 ? based on what? – jsedano Mar 15 '13 at 15:43
  • Can you please post some code to show what kind of elements you are comparing? – Ian R. O'Brien Mar 15 '13 at 15:44
  • TreeMap can do the sorting for you. But in order for us to know what you are trying to sort it by u have to tell us! – Kevin Mar 15 '13 at 15:45
  • Ahh sorry missed it out, the K,V are String,Integer. I still need to know which keys have the highest values.I have tried TreeMap but it only sorts by key as defined in the specification. – Tohmas Mar 15 '13 at 15:58
  • http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java – Achintya Jha Mar 15 '13 at 16:01

7 Answers7

3

Maybe you should implement the Comparable Interface to your value objects stored in the hashmap. Then you can create a array list of all values:

List<YourValueType> l = new ArrayList<YourValueType>(hashmap.values());
Collection.sort(l);
l = l.subList(0,10);

Regards

sk2212
  • 1,688
  • 4
  • 23
  • 43
  • Quite good solution. I just needed something similar. Since you are only providing values, but I also needed the keys. I made a slight modification and added a Comparator in order to use the entry set. The comparator has to compare the entry values in descending order. List> results = new ArrayList<>(hashmap.entrySet()); Collections.sort(results, new EntryComparator()); results = results.subList(0, 10); – Sebastian D'Agostino Apr 15 '17 at 22:05
  • 1
    I am adding it as another answer because it looks bad as a comment – Sebastian D'Agostino Apr 15 '17 at 22:06
3
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Testing {

    public static void main(String[] args) {

        HashMap<String,Double> map = new HashMap<String,Double>();
        ValueComparator bvc =  new ValueComparator(map);
        TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc);

        map.put("A",99.5);
        map.put("B",67.4);
        map.put("C",67.4);
        map.put("D",67.3);

        System.out.println("unsorted map: "+map);

        sorted_map.putAll(map);

        System.out.println("results: "+sorted_map);
    }
}

class ValueComparator implements Comparator<String> {

    Map<String, Double> base;
    public ValueComparator(Map<String, Double> 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
    }
}
Biswajit
  • 2,434
  • 2
  • 28
  • 35
  • Oh wow, I think that might just do it, going to give it a shot now,THANKS! – Tohmas Mar 15 '13 at 16:02
  • @Biswajit, can you explain me the complexity of this code? Your code is working perfectly and its very easy approach, just wanted to calculate the complexity of this code.... – Rushi Feb 06 '15 at 00:35
  • @Biswajit, you code is great, but how do you ensure the size of TreeMap is 10 at all times? Because you only want to TOP TEN right? Everytime you insert a key-value pair into the Tree Map, you need to check if the current size is greater than ten, if it is, you need to delete the smallest key-value pair in the TreeMap. How do you do this last part in the code? I didn't think people would answer my question here, so I asked a new question referencing this post [Here](http://stackoverflow.com/questions/37244198/how-to-maintain-a-java-treemap-size-to-be-a-constant-while-adding-key-value-pair) – Awesome_girl May 16 '16 at 16:07
1

I am afraid you'll have to iterate over the entire map. Heap is a commonly-used data structure for finding top K elements, as explained in this book.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

If you are trying to get the 10 highest values of the map (assuming the values are numeric or at least implementing Comparable) then try this:

List list = new ArrayList(hashMap.values());
Collections.sort(list);
for(int i=0; i<10; i++) {
   // Deal with your value
}
aymeric
  • 3,877
  • 2
  • 28
  • 42
0

Let's assume you have a Map, but this example can work for any type of

Map<String, String> m = yourMethodToGetYourMap();
List<String> c = new ArrayList<String>(m.values());
Collections.sort(c);
for(int i=0 ; i< 10; ++i) {
    System.out.println(i + " rank is " + c.get(i)); 
}
Jirawat Uttayaya
  • 1,039
  • 9
  • 11
0

I base my answer in this one from sk2212

First you need to implement a descending comparator:

class EntryComparator implements Comparator<Entry<String,Integer>> {

    /**
     * Implements descending order.
     */
    @Override
    public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
        if (o1.getValue() < o2.getValue()) {
            return 1;
        } else if (o1.getValue() > o2.getValue()) {
            return -1;
        }
        return 0;
    }

}

Then you can use it in a method such as this one for the attribute "hashmap":

public List<Entry<String,Integer>> getTopKeysWithOccurences(int top) {
    List<Entry<String,Integer>> results = new ArrayList<>(hashmap.entrySet());
    Collections.sort(results, new EntryComparator());
    return results.subList(0, top);
}
Community
  • 1
  • 1
Sebastian D'Agostino
  • 1,575
  • 2
  • 27
  • 44
0
public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        // Initialize map
        System.out.println(getTopKeysWithOccurences(map, 10));
}

public static List<Entry<String,Integer>> getTopKeysWithOccurences(Map mp, int top) {
        List<Entry<String,Double>> results = new ArrayList<>(mp.entrySet());
        Collections.sort(results, (e1,e2) -> e2.getValue() - e1.getValue());
        //Ascending order - e1.getValue() - e2.getValue()
        //Descending order - e2.getValue() - e1.getValue()
        return results.subList(0, top);
}
Neetu T
  • 1
  • 1