Win a copy of Functional Reactive Programming this week in the Other Languages forum!

# Sorting values in a map

F Merchant
Greenhorn
Posts: 11
I want to sort a map in decreasing order based on the values.
However, the sorted map is being displayed as empty {}.
Is there something wrong with my logic?

Thanks!

Sheriff
Posts: 14691
16
• 1
Setting the original map in a Comparator class will not populate the new TreeMap. The TreeMap uses your ValueComparator to compare its values, that's all. But it will remain empty. Maybe you wanted to do :

F Merchant
Greenhorn
Posts: 11
I tried that...solved the {} problem.
But I think my logic is wrong.
The map contains words and the frequency of their occurence.
{to=5, scs=1, basis=1, for=2, determine=1, by=1...}
Now I want to sort the map based on frequency.
But I'm getting a map with the words sorted in alphabetical order.
{a=7, ae=1, aerodynamics=1, after=1...}

Campbell Ritchie
Sheriff
Posts: 50225
79
The problem is that you are sorting on the K part of the Map.Entry, and you want to sort on the V. That is awkward. You cannot simply sort of the V, nor can you put them into a Map<Integer, String> because you will suffer duplicate Ks. You cannot simply put all the pairs into a TreeSet<Map.Entry<String, Integer>> and sort on the Integer, because you will get collisions too.
In both cases the collisions will cause entries to be lost.
It is worth seeing whether you can find a bidirectional map which serves your purposes. I don’t think there is one in the Oracle/Sun API, so try Apache Commons.
You can design your own tree set, taking the Integer as the value to sort on, and putting duplicate entries into Lists within the tree.
You can put all the entries into a List (or an array) and sort the List. If you sort the List on the Integer first, and sort it with a “stable” algorithm on the String later, you will get the Strings in ASCIIbetical order within the frequencies.

Martin Vajsar
Sheriff
Posts: 3752
62
I'd suggest creating a class (say, Word) that would keep the word and its frequency, a comparator for this class which would compare the frequencies, creating instances of the Word class from the original map, putting these instances into a List<Word> (an ArrayList, probably) and sorting that list.

Also note that your ValueComparator class has a bug: an instance will not be equal to itself (your compare function never returns 0). Even if you somehow managed to get the scheme working (it would be possible, just very cumbersome), you wouldn't be able to retrieve values from the map using a string as a key. (I bumped into exactly this same problem very recently )

F Merchant
Greenhorn
Posts: 11
Oh ok....I'll try again.
Thanks!

F Merchant
Greenhorn
Posts: 11
I found this code: http://ideone.com/dq3Lu
But I can't understand one thing. In the compare(), we only take care of duplicate values. Where(or which statement) sorting is taking place.

Jeff Verdegan
Bartender
Posts: 6109
6
F Merchant wrote:I found this code: http://ideone.com/dq3Lu
But I can't understand one thing. In the compare(), we only take care of duplicate values. Where(or which statement) sorting is taking place.

If the values are not equal, then we already have the comparison result (negative or positive) so we just return that.

If they're equal (comparison returned 0), then we compare the keys and return that comparison result.

Note that there's no sorting code here. This is just comparison code to order any two or our objects. The sort routine will call our comparison method on various pairs of objects and reorder them or not depending on the results.

F Merchant
Greenhorn
Posts: 11
Understood! Thanks!!
So basically I cannot sort a map based on the value.
But for temporary ordering, something like the above code can be done.

Jeff Verdegan
Bartender
Posts: 6109
6
F Merchant wrote:Understood! Thanks!!
So basically I cannot sort a map based on the value.

You could write your own Map implementation whose iteration order is based on the sort order of the values. Heck, there may even be one floating around at apache or sourceforge.

But for temporary ordering, something like the above code can be done.

Yes.

Winston Gutkowski
Bartender
Posts: 10527
64
• 2
F Merchant wrote:Understood! Thanks!!
So basically I cannot sort a map based on the value.
But for temporary ordering, something like the above code can be done.

If it works, sure; but it seems to me that you're going all around the houses, when doing what Martin suggested (a Word class) would put you in position to sort a bunch of words exactly as you want. And in that case, do you really care whether it's a Map or a List ?

Hint: Implementing a Map that's dynamically sortable in lots of ways is probably overkill for what you need.

Winston

BTW: I broke up those enormous comment lines in your code. Please re-read the UseCodeTags (←click) page thoroughly. Thanks.

F Merchant
Greenhorn
Posts: 11
Hmmm....ok. I'll try out the Word class. Thanks everyone!
And Winston, I'll be careful about the code tags!