11

I have one problem

HashMap<String, List<AppPrjMilestone>> dateMilestoneMap
                                 = new HashMap<String, List<AppPrjMilestone>>();

I am putting dynamic key in Hashmap object like this:

dateMilestoneMap.put(""+crateDate,value);

Finally I am getting result like this:

("28/01/2012",value)
("01/01/2012",value)
("26/01/2012",value)

I want return key value pairs in desc or asc order. How can I do that?

Mat
  • 202,337
  • 40
  • 393
  • 406
Naveen A
  • 533
  • 4
  • 8
  • 16
  • 1
    Try a TreeMap and read the Javadoc: http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html – home Jan 28 '12 at 17:09
  • Any reason you're using a Map instead of a List? – kba Jan 28 '12 at 17:10
  • TreeMap is the no-fuss solution here. There's more discussion on it at http://stackoverflow.com/questions/7860822/sorting-hashmap-based-on-keys – Bob Dec 12 '16 at 20:06

5 Answers5

25

HashMaps do not store the sorted order of keys by definition. You can however accomplish this by acquiring an array of the keys via: Object[] keys = map.keySet().toArray(); Then sorting the list with Arrays: Arrays.sort(keys); and finally iterating through each key and retrieving the value from the HashMap.

for(Object key : keys) { System.out.println(map.get(key)); }

The sorting step here will make the algorithm run in O(n lg n) rather than O(n) which would be possible using a sorting data structure.

This will sort the list lexicographically. Since it looks like your question uses the common US date format, this will sort the list by day, then month and finally year. This is not likely correct. You can either use a year, month, day string format of the date, or adopt a more appropriate key object. Joda-Time's DateTime and DateTimeComparator would be quite useful. Simply use DateTime as the key and a DateTimeComparator instance when calling Arrays.sort(keys, comparator);.

allingeek
  • 1,378
  • 8
  • 16
  • Why not `Collection.sort`? And why not use a comparator on `Map.Entry`? – Tom Hawtin - tackline Jan 28 '12 at 17:28
  • 1
    Collections.sort(...) works but takes a List, which HashMap does not implement. You would have to convert it to something like an ArrayList via new ArrayList(map). In the end, its basically the same mechanism. If the keys are Strings, they will be sorted lexicographically. – allingeek Jan 28 '12 at 17:40
  • -1 Also, I have to ding this answer because this still won't sort by date, because the String representation he uses for the date _doesn't sort by date!_ – user949300 Jan 28 '12 at 17:47
  • @allingeek Ah yes, I was thinking `List` instead of `Set` for `entrySet`. – Tom Hawtin - tackline Jan 28 '12 at 17:59
  • I've addressed the sorting order in my answer. @user949300 This should make you a bit happier. Although, I'm pretty sure your suggestion to sort Map.keySet() is exactly what I'm talking about. You cannot sort a Set, as it is also unordered. – allingeek Jan 28 '12 at 19:17
  • @allingeek the algorithm would run in O(n lg n) regardless if using a sorting data structure. – j-a Jun 08 '18 at 07:29
  • @j-a Well, this was 6 years ago. But I'm guessing what I meant was that by using a sorted data structure you would only pay the sorting penalty when building the set. That would make sorted list enumeration linear vs paying the sorting penalty every time. – allingeek Jun 08 '18 at 18:19
4

Keys of a map are stored in a Set which can not be sorted. You can do it by adding the keys of the map set into a List and sorting that instead.

e.g.

List<Date> sortedKeys = new ArrayList<Date>(dateMilestoneMap.size());
sortedKeys.addAll(dateMilestoneMap.keySet());
Collections.sort(sortedKeys); //sorts in ascending date order 
                             //(pass in custom Comparator to sort differently)..

Here I've used the Date class which is much better for storing dates than plain Strings.

Mark Rhodes
  • 10,049
  • 4
  • 48
  • 51
  • 1
    You can actually do it a little more directly: `List sortedKeys = new ArrayList(dateMilestoneMap.keyset());` `Collections.sort(sortedKeys);` – Elliptica Nov 30 '18 at 23:52
2

HashMap doesn't provide any ordering when you iterate over it (or even guarantee that the order will stay the same if you loop multiple times). If you want a natural ordering over the keys, try TreeMap. Note that your strings are formatted dd/mm/yy, so when the TreeMap orders them it's going to be ascending by day first, not by year, which is probably not what you want. You should either use strings like yy/mm/dd, switch to using a class that encapsulates that information better like Date, or define your own Comparator when you construct the TreeMap that knows how to sort your dd/mm/yy strings in the right order

Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
  • 1
    I'm pretty sure the question was about sorting a keys of a HashMap. – allingeek Jan 28 '12 at 19:09
  • @allingeek I'm not. He was vague, but I think he wants to loop over the map and get the keys in ascending or descending order, so he should just use a map that provides that. If it's literally "I need to use a HashMap, but I want the keys in order anyway" he should probably specify that, but I think it's more "I'm using HashMap but it doesn't do what I want; how do I deal with it?" – Michael Mrozek Jan 28 '12 at 19:19
  • Making a TreeMap copy of the HashMap might actually be the best way to sort the keys. – Louis Wasserman Jan 28 '12 at 21:04
2

HashMap doesn't define the order of iteration over the elements. If you want to retrieve elements sorted by key use the TreeMap instead. However, since you store the strings in the format "DD/MM/YYYY" the order will likely be not the one you want, so either use the Date as a key or at least string of the form like "YYYY-MM-DD".

vitaut
  • 49,672
  • 25
  • 199
  • 336
0

I'd suggest that you change the HashMap key from String to Date, e.g. HashMap<Date, List<AppPrjMilestone>>. That should do the trick.

oops - make that a TreeMap<Date, List<AppPrjMilestone>>

user949300
  • 15,364
  • 7
  • 35
  • 66