Sort HaspMap on Values: Java

This Comment will be submitted for moderation and will not be accessible to other users until it has been approved.


2 points

I'm trying to sort a HashMap by values. I know that it might not be "good style", but it would save a lot of work, as I wouldn't have to rewrite lots of code if I could just get the HashMap sorted by value.

After lots of searching and trial and error cases I'm still stuck.

The HashMap itself is still unsorted.

 import java.util.* ;
public class H
{
    static HashMap first = new HashMap();
    static
    {
        first.put("20030120" , new Integer (56));
        first.put("20030118" , new Integer (19));
        first.put("20030125" , new Integer (25));
        first.put("20030122" , new Integer (32));
        first.put("20030117" , new Integer (67));
        first.put("20030123" , new Integer (34));
        first.put("20030124" , new Integer (42));
        first.put("20030121" , new Integer (19));
        first.put("20030119" , new Integer (98));
    }
    public static void main( String[] args )
    {
        ArrayList as = new ArrayList( first.entrySet() );
 
        Collections.sort( as , new Comparator() {
            public int compare( Object o1 , Object o2 )
            {
                Map.Entry e1 = (Map.Entry)o1 ;
                Map.Entry e2 = (Map.Entry)o2 ;
                Integer first = (Integer)e1.getValue();
                Integer second = (Integer)e2.getValue();
                return first.compareTo( second );
            }
        });
 
        Iterator i = as.iterator();
        while ( i.hasNext() )
        {
            System.out.println( (Map.Entry)i.next() );
        }
    }
}    

Now my qustion is, how to put those sorted Entry sets back in a HashMap?
This is probably very easy, but I'm just not seeing it.

Thanks in advance for reading. Any input is appreciated.



1 point

Give up. HashMap won't store your data sorted in any order, let alone by value.

TreeMap will sort data inserted in arbitrary order, but only by the key. You can write a comparator that tries to sort by values given the key, but it's a mess and won't always work right.

LinkedHashMap, on the other hand, will store items in insertion order. So if you sort by value, as you've shown here, then insert into a LinkedHashMap in sorted order, they'll stay that way.

Anonymous's picture
Created by Anonymous
4 points

LinkedHash is the best way to go about what you want, second option could be a custom container with a comparater built in to contain you sorting criteria.

Anonymous's picture
Created by Anonymous
2 points

Something like this, maybe?

Map someMap= new LinkedHashMap();
 
someMap.put("key1","c");
someMap.put("key2","a");
someMap.put("key3","b");
 
List mapKeys = new ArrayList(someMap.keySet());
List mapValues = new ArrayList(someMap.values());
 
someMap.clear();
 
TreeSet sortedSet = new TreeSet(mapValues);
 
Object[] sortedArray = sortedSet.toArray();
 
int size = sortedArray.length;
 
//a) Ascending sort
 
for (int i=0; i<size; i++)
{
 
//System.out.println(sortedArray[i]);
 
someMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])), sortedArray[i]);
 
}
 
System.out.println(someMap);
 
someMap.clear();
 
//b) Descending sort
 
for (int i=size; i>0;)
{
 
someMap.put(mapKeys.get(mapValues.indexOf(sortedArray[--i])), sortedArray[i]);
 
}
 
System.out.println(someMap);

Regards,

Artem D. Yegorov

Anonymous's picture
Created by Anonymous
3 points

Artem, that works if all the values are unique, which isn't true in my case. I ened up with the below. Maybe somebody can make it better, but it does deal with duplicate values.

public LinkedHashMap sortHashMapByValues(HashMap passedMap, boolean ascending) {
 
  List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
 
if (!ascending)
Collections.reverse(mapValues);
 
LinkedHashMap someMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
if (passedMap.get(key).toString().equals(val.toString())) {
passedMap.remove(key);
mapKeys.remove(key);
someMap.put(key, val);
break;
}
}
}
return someMap;
} 

Anonymous's picture
Created by Anonymous

Post Comment

  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby>. Beside the tag style "<foo>" it is also possible to use "[foo]". PHP source code can also be enclosed in <?php ... ?> or <% ... %>.