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

Posted

技术标签:

【中文标题】从 HashMap 中检索的值的顺序是插入顺序吗【英文标题】:Is the order of values retrieved from a HashMap the insertion order 【发布时间】:2011-01-09 19:52:45 【问题描述】:

我正在尝试找出/可以检索 HashMap 中的值的顺序。这是相同的代码sn-p。

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。

【问题讨论】:

只需使用LinkedHashMap。 @Raedwald 好的,但她确实多次询问插入顺序,看起来 LinkedHashMap 可能值得一看。 【参考方案1】:

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

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

【讨论】:

我认为 OP 是在问为什么 HashMap 出现 在他的用例中保留插入顺序。很明显,他期望迭代顺序更加随机。 虽然排序是针对键的,但大多数这些映射实际上存储键/值条目 (Map.Entry)。因此,值通常也会以与其关联键相同的顺序出现。【参考方案2】:

这些值按照插入的顺序打印。这是真的吗?我期望这些值以随机顺序打印。

HashMap API 没有定义迭代的顺序。

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

在您的情况下,您使用的是 Integer 键,这意味着键的哈希值就是键值本身。此外,您按密钥顺序插入了条目。这导致(幸运的是!)迭代顺序与插入顺序相匹配。但是如果你不断插入更多的键,你会发现迭代顺序“环绕”。然后随着表格经过一系列调整大小,顺序将逐渐变得越来越混乱。

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

如果顺序很重要,请尝试 LinkedHashMap...参见 JavaDoc

公共类 LinkedHashMap 扩展 哈希映射

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

【讨论】:

【参考方案5】:

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

有一个不错的跳过列表demo applet。

【讨论】:

【参考方案6】:

不,在 HashMap 的情况下不保留顺序(如果您想要排序实现。) 如果您希望对键进行排序,可以使用 TreeMap。

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

对于 TreeMap,你得到 - [2=50],[3=1],[14=1],[20=4] -> 树状图

【讨论】:

以上是关于从 HashMap 中检索的值的顺序是插入顺序吗的主要内容,如果未能解决你的问题,请参考以下文章

如何按照插入的顺序从字典中检索项目?

什么时候在java中使用linkedhashmap而不是hashmap?

如何从它们插入哈希图中的顺序打印哈希图值

07顺序表的操作

如何在 HashMap 中保留插入顺序? [复制]

HashMap为啥比数组查询速度快?