如何在Java中以相反的顺序迭代HashMap

23

我尝试了好几个小时,但是没有找到最佳方法来实现HashMap的反向迭代,这是我拥有的HashMap。

      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 }));  
            }

我也看过TreeMap的例子,

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

但是treemap也是按升序排列的,我想要的是按降序排列。


3
HashMap没有顺序,因此它们也没有反转顺序。 - user207421
请参考 https://dev59.com/vmw05IYBdhLWcg3wiyfg - rogerdpack
12个回答

49

如何以迭代哈希映射的逆序顺序?

HashMap 不定义其元素的任何特定顺序。因此,“逆序”顺序也未定义。

对于 TreeMap,您可以使用descendingMap() 方法实现。


25

HashMap没有特定的顺序,但你可以使用TreeMap。

也许这个简单的例子能帮到你:

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)));
        }

7
请注意,这种方法在内存使用和时间复杂度方面相当低效。 - NPE
1
NPE的回答似乎更为恰当,因为它不需要创建ArrayList所需的空间/时间。 - jwheels
我不喜欢这个方法,因为它依赖于密钥空间中的整数值。实际上,我更喜欢JB Nizet的答案,即反转默认排序顺序,这样无论在您的密钥空间中有什么类型的值,都可以轻松遍历键。 - Austin A

15

HashMap不保持key之间的任何顺序。

TreeMap按照它们的自然顺序或者在构造映射时通过传递比较器强制执行的顺序来排序其键。因此,如果您想要将整数键按相反的顺序排序,请以以下方式构造TreeMap:

Map<Integer, List<String>> sortedMap = 
    new TreeMap<Integer, List<String>>(Collections.reverseOrder());

虽然我认为这是一个不错的方法,但我觉得TreeMap#descendingMap()更加优雅。U_U - Campa

6
Map<Integer, List<String>> sortedMap = new TreeMap<Integer, List<String>>(Collections.reverseOrder());

Collections.reverseOrder() keeps the map sorted in descending order.

6
您可以使用TreeMap#descendingKeySet方法。
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--


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());
    }

NPE思想的实现。

4
由于 这个,你无法在 HashMap 上进行反向迭代:

此类不保证地图的顺序;特别是,它不能保证随时间而保持常数的顺序。

你应该使用一个 LinkedHashMap:

此实现与 HashMap 不同之处在于,它维护一个双向链接列表,通过其中所有条目。这个链接列表定义了迭代排序,通常是键插入到映射中的顺序(插入顺序)。请注意,如果将键重新插入到映射中,插入顺序不会受到影响。 (当在调用m.containsKey(k)会立即返回true时调用m.put(k,v)时,将键k重新插入到映射m中。)


2
不幸的是,即使是JDK的LinkedHashMap也没有轻松访问其内部双向链表以允许您以“反向顺序”遍历,所以我猜你基本上必须“自己编写”(使用HashMap组合的链表)类,不幸的是。Guava可能有一些有用的东西... - rogerdpack
不幸的是,即使是JDK的LinkedHashMap也无法轻松访问其内部的双向链表,以允许您以“反向顺序”遍历。请参见https://dev59.com/cHI-5IYBdhLWcg3wR2Jr#1936472。 - rogerdpack

4

HashMap不是有序的集合。使用TreeMap替代,它具有descendingKeySet用于反向迭代。请参阅javadocsLinkedHashMap也是一个不错的选择。


3

2

但是treemap也会按升序排列,我想要的是降序排列。

实现一个Comparator,将其与自然顺序相反进行比较,然后正常迭代即可获得反向迭代。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接