23

I am trying this for some hour but not finding any best approach to achieve iteration of hashmap in reverse order, this is the hashmap I have.

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

             for(Integer key : map.keySet()) {
                List<String> value = map.get(key);
                List<Map<String,?>> security = new LinkedList<Map<String,?>>();  
                for(int ixy = 0; ixy < value.size()-1; ixy++){
                    security.add(createItem(value.get(ixy), value.get(ixy+1))); 
                }
                adapter.addSection(Integer.toString(key), new SimpleAdapter(getApplicationContext(), security, R.layout.list_complex, new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));  
            }

I have seen example of TreeMap as well,

             Map<Integer, List<String>> sortedMap = new TreeMap<Integer, List<String>>(map);

But treemap also gives in ascending order, what I want is in descending order.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Programmer
  • 5,360
  • 10
  • 37
  • 61

12 Answers12

49

best approach to acheive iteration of hashmap in reverse order

HashMap does not define any particular ordering of its element. Therefore the "reverse" order isn't defined either.

For a TreeMap, you can use descendingMap().

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

Hashmap does not have specific order. But you can use TreeMap.

Perhaps this simple example can help you :

Map<Integer, String> map = new TreeMap<Integer, String>();
        map.put(1, "abc1");
        map.put(2, "abc2");
        map.put(3, "abc3");

        ArrayList<Integer> keys = new ArrayList<Integer>(map.keySet());
        for(int i=keys.size()-1; i>=0;i--){
            System.out.println(map.get(keys.get(i)));
        }
Kshitij
  • 8,474
  • 2
  • 26
  • 34
  • 7
    Note that this method is rather inefficient both in terms of memory usage and time complexity. – NPE May 15 '12 at 14:32
  • 1
    NPE's answer seems much more appropriate, since it does not require the space/time required to create the ArrayList` – jwheels Feb 28 '13 at 03:25
  • I don't like this because it depends on an integer value in the key space. I actually prefer JB Nizet's answer of reversing the default sorting order, that way, regardless of the type of value in your key space, you can just iterate over the keys. – Austin A Feb 12 '15 at 03:01
15

A HashMap doesn't maintain eny order between keys.

A TreeMap orders its keys by their natural order, or by the order imposed by a comparator that you pass when constructing the map. So if you want to have Integer keys ordered in reverse order, construct the TreeMap this way:

Map<Integer, List<String>> sortedMap = 
    new TreeMap<Integer, List<String>>(Collections.reverseOrder());
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
6
Map<Integer, List<String>> sortedMap = new TreeMap<Integer, List<String>>(Collections.reverseOrder());

Collections.reverseOrder() keeps the map sorted in descending order.
Ravi Jain
  • 1,452
  • 2
  • 17
  • 41
6

You can use TreeMap#descendingKeySet method.

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

for(Integer key : map.descendingKeySet()) {
    List<String> value = map.get(key);
    List<Map<String,?>> security = new LinkedList<Map<String,?>>();  
    for(int ixy = 0; ixy < value.size()-1; ixy++){
        security.add(createItem(value.get(ixy), value.get(ixy+1))); 
    }
    adapter.addSection(Integer.toString(key), new SimpleAdapter(getApplicationContext(), security, R.layout.list_complex, new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));
} 

Reference:

https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#descendingKeySet--

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
4

You can't iterate over a HashMap in reverse because of this:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

What you should use is a LinkedHashMap:

This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map. (A key k is reinserted into a map m if m.put(k, v) is invoked when m.containsKey(k) would return true immediately prior to the invocation.)

npinti
  • 51,780
  • 5
  • 72
  • 96
  • 2
    unfortunately even the JDK LinkedHashMap doesn't have easy access to its internal double linked list to allow you to traverse in "reverse order" so I guess you'd basically have to "roll you own" (linked list with HashMap combined) class, unfortunately. Guava might have something that helps... – rogerdpack Dec 09 '15 at 07:08
  • unfortunately even the JDK LinkedHashMap doesn't have easy access to its internal double linked list to allow you to traverse in "reverse order" see also http://stackoverflow.com/a/1936472/32453 – rogerdpack Dec 09 '15 at 16:33
4

The hashmap is not an ordered collection. Use TreeMap instead, which has descendingKeySet for reverse iteration. See the javadocs. LinkedHashMap is also a good choice.

zeller
  • 4,904
  • 2
  • 22
  • 40
4
    TreeMap<Integer, String> map = new TreeMap<Integer, String>();
    map.put(1, "abc1");
    map.put(2, "abc2");
    map.put(3, "abc3");
    NavigableMap<Integer, String> nmap = map.descendingMap();
    for (NavigableMap.Entry<Integer, String> entry : nmap.entrySet()) {
        System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
    }

An implementation of NPE idea.

Bruce
  • 105
  • 8
3

Perhaps you need a NavigableMap, like a TreeMap.

Marat Salikhov
  • 6,367
  • 4
  • 32
  • 35
2

But treemap also gives in asecding order, what i want is in descending order.

Implement a Comparator that will compare it reverse than natural order and then just iterate normally you will have reverse iteration

jmj
  • 237,923
  • 42
  • 401
  • 438
2

Use insted:

new TreeMap<>(Collections.reverseOrder())

and you will get what you want.

0

I've found that the Iterators obtained from Java Hashtable via: Hashtable.values().iterator() and Hashtable.keys().asIterator() are both in reverse order by default. One oddity, The values().iterator has a first final value of "0" which I didn't add when populating it.

Jack Mason
  • 141
  • 2
  • 3