从HashMap检索的值的顺序是插入顺序

时间:2010-01-27 05:31:38

标签: java hashmap

我正在尝试找出可以检索HashMap中的值的顺序。下面是代码片段。

import java.util.HashMap;

public class HashMapExample {

   public static void main(String[] args) {
       HashMap<Integer, String> hashmap = new HashMap<Integer, String>();
       hashmap.put(1, "apple" );
       hashmap.put(2, "lemon" );
       hashmap.put(3, "orange" );
       hashmap.put(4, "banana" );
       hashmap.put(5, "litchi" );
       hashmap.put(6, "mango" );
       hashmap.put(7, "papaya" );

       System.out.println(hashmap.size());

       for (String key : hashmap.values()) {
           System.out.println(key);
       }
   }
}

输出:

7
apple
lemon
orange
banana
litchi
mango
papaya

值按照插入顺序打印。一般来说这是真的吗?我期待值以任意顺序打印。这是使用Java 6。

6 个答案:

答案 0 :(得分:81)

来自Javadoc:HashMap“类不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。”

如果您需要一致的排序,可以使用LinkedHashMap(用于插入/访问顺序)或TreeMap(用于比较顺序)。请注意,这些维护键的顺序,而不是值。

答案 1 :(得分:61)

  

值按照插入顺序打印。一般来说这是真的吗?我期待值以随机顺序打印。

HashMap API未定义迭代顺序。

但是,如果查看HashMap的实现,可以推断迭代顺序,键的哈希值,键的插入顺序和哈希表的大小之间存在复杂的瞬态关系。如果哈希表调整自身的大小,这种关系就会被扰乱。

在您的情况下,您正在使用Integer键,这意味着键的哈希值本身就是键值。此外,您按键顺序插入条目。这导致(偶然!)到与插入顺序匹配的迭代顺序。但是如果你继续插入更多的键,你会发现迭代顺序“包裹”。然后,当表格经历一系列调整后,订单将逐渐变得越来越多。

简而言之,您所看到的是哈希表实现的人工制品,而不是您可以(或应该)明智地使用的东西。尤其是因为可以从一个Java版本更改为下一个版本。

答案 2 :(得分:9)

你正在追求LinkedHashMap。在doco中,与HashMap的不同之处在于它维护着一个贯穿其所有条目的双向链表

答案 3 :(得分:5)

如果订单很重要,请尝试使用LinkedHashMap ...请参阅JavaDoc

  

公共类LinkedHashMap扩展   HashMap中

     

哈希表和链表   Map接口的实现,   具有可预测的迭代顺序。这个   实现与HashMap的不同之处在于   它保持一个双向链表   贯穿其所有条目。   此链接列表定义迭代   订购,通常是订单   其中键被插入   map(插入顺序)。注意   如果a,插入顺序不受影响   键被重新插入地图中。 (一个   如果将密钥k重新插入到映射中   m.put(k,v)在被调用时被调用   m.containsKey(k)将返回true   在调用之前。)

答案 4 :(得分:1)

相关集合是java.util.concurrent的ConcurrentSkipListMapskiplist允许您按键顺序遍历条目,并以随机顺序查看它们(但不如HashMap快)。

有一个很好的跳过清单demo applet

答案 5 :(得分:-1)

否,如果是HashMap,则不保留顺序(如果要排序的实现)。 如果要对键进行排序,可以使用TreeMap。

例如- {[3 = 1],[2 = 50],[20 = 4],[14 = 1]}-> HashMap

对于TreeMap,您可以获得- {[2 = 50],[3 = 1],[14 = 1],[20 = 4]}-> TreeMap