1

I have a HashMap defined as follows

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

I am then storing data from databse in this hashmap and displaying the contents as follows on the console where entries towards the left of ---> are ID's and entries towards right are tags used by this ID

165767--->[dual-boot, windows, uninstall, ati, graphics, multiple-monitors]
6873 --->[kubuntu, re-installation]
34228--->[11.10, unity, launcher, libreoffice, icons]

I want to sort the ID's in descending order based on the number of tags that they have used i.e. based on map.get(key).size() so that the output should be ID 165767 followed by 34228 and then 6873 and so on.

I tried doing it with TreeMap but I am not able to figure out how to do it based on size and not the value of key and that too in descending order.

4

3 回答 3

3

This creates a sorted list of ids.

List<String> sortedIds = new ArrayList<String>(map.getKeys());
Collections.sort(sortedIds, new Comparator<String>() {
    public int compare(String a, String b) {
        return map.get(b).size() - map.get(a).size();
    }
});

Not that you would never to maintain a SortedMap (like TreeMap), sorted on mutable values (like the length of an ArrayList). Since the sorted order is used to look up values, it could cause very big problems if "id123" became greater than "id456" without the Collection knowing about it.

于 2013-11-09T20:36:00.577 回答
0

EDIT :

My output should be sorted based on number of tags and not the size of ID

Map<String, ArrayList<String>>  map = new TreeMap<String, ArrayList<String>>();


map.put("165767",new ArrayList<String>(Arrays.asList("dual-boot", "dual-boot", "windows", "uninstall", "ati", "graphics", "multiple-monitors")));
map.put("6873",new ArrayList<String>(Arrays.asList("kubuntu", "kubuntu", "re-installation")));
map.put("0000000000000000",new ArrayList<String>(Arrays.asList("test","test", "test")));
map.put("0125",new ArrayList<String>(Arrays.asList("dual-boot", "windows", "uninstall", "ati", "graphics", "multiple-monitors")));


for(ArrayList<String> l : map.values()){
    Set<String> hs = new HashSet<>();
    hs.addAll(l);
    l.clear();
    l.addAll(hs);
}

List<ArrayList<String>> l = new ArrayList<>(map.values());
Collections.sort(l, new Comparator<ArrayList<String>>(){
    public int compare(ArrayList<String> s1, ArrayList<String> s2){
        return Integer.compare(s2.size(), s1.size());                
    }});

for(ArrayList<String> a : l){
    Iterator<Entry<String, ArrayList<String>>> iter = map.entrySet().iterator();
    while (iter.hasNext()) {
        Entry<String, ArrayList<String>> e = iter.next();
        if(e.getValue().equals(a)){

            System.out.println(e.getKey() + "-" + a);
            iter.remove();
        }
    }
}

Output :

0125-[uninstall, dual-boot, graphics, windows, ati, multiple-monitors]
165767-[uninstall, dual-boot, graphics, windows, ati, multiple-monitors]
6873-[re-installation, kubuntu]
0000000000000000-[test]
于 2013-11-09T20:42:56.533 回答
0

I had a similar scenario and this code worked for me (sometimes I have nulls):

     private static Map<Object,List<Object>> sortByArraySizeDesc(Map<Object,List<Object>> map) {
         List<List<Object>> list = new LinkedList(map.entrySet());
         Collections.sort(list, new Comparator() {
              public int compare(Object o1, Object o2) { 
                  if (o1 == null && o2 == null) { return 0; }
                  else if (o1 == null) { return 1;}
                  else if (o2 == null) { return -1; }
                  int size1 = ((List) ((Map.Entry) (o1)).getValue()).size();
                  int size2 = ((List) ((Map.Entry) (o2)).getValue()).size();
                  return size2 - size1;
              }
         });

        Map res = new LinkedHashMap();
        for (Iterator it = list.iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry)it.next();
            res.put(entry.getKey(), entry.getValue());
        }
        return res;
    } 
于 2015-05-25T01:23:21.957 回答