我正在尝试找出可以检索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。
答案 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的ConcurrentSkipListMap。 skiplist允许您按键顺序遍历条目,并以随机顺序查看它们(但不如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