这是因为我注意到Map中相同的键值对并不总是以相同的顺序排列。
java.util.HashMap
是无序的,你不能也不应该假设除此之外的任何内容。
这个类不保证映射表的顺序;特别地,它不保证顺序会随时间保持不变。
java.util.LinkedHashMap
使用插入顺序。
相对于
HashMap
,这个实现保留了一个双向链表,用以在所有条目中进行迭代。这个链表定义了迭代顺序,通常是按照键被插入到映射表的顺序(插入顺序)。
java.util.TreeMap
是一个SortedMap
,使用自然排序或自定义键排序。
这个映射表根据其键的自然排序或创建时提供的
Comparator
进行排序,具体取决于使用哪个构造函数。
首先:HashMap
特别是 没有 提供稳定和/或定义的排序。所以你观察到的任何东西都只是一些实现细节,你 绝不能 以任何方式依赖它。
由于了解看似随机排序的原因有时很有用,以下是基本思想:
HashMap
有许多 bucket(实现为数组)来存储条目。
将项添加到映射中时,它根据其 hashCode
的值和 HashMap
的桶大小分配到一个桶中。(注意,桶可能已经被占用,这称为冲突。虽然可以优雅地正确处理,但我会忽略该处理过程,因为它不影响概念)。
条目的感知顺序(例如通过迭代 Map
返回的顺序)取决于那些桶中的条目的顺序。
每当大小重新哈希(因为 map 超过其满度阈值),那么桶的数量会更改,这意味着每个元素的位置可能会更改,因为桶的位置也是根据桶的数量推导出来的。
HashMap
不排序。如果需要按键值排序的地图,请改用 TreeMap
。
从 TreeMap
的 JavaDocs 中可以看到:
从基于红黑树实现的 SortedMap 接口,此类保证地图将按升序键排序,根据键类的自然顺序(参见 Comparable)或在创建时提供的比较器进行排序,具体取决于使用哪个构造函数。
HashMap
的文档中可以看到:
此类不保证映射的顺序;特别是,它不能保证顺序随时间保持不变。
Map
不是一个有序的数据结构 - 你不应该依赖于HashMap
中的条目以某种顺序出现。一些Map
实现,如LinkedHashMap
和TreeMap
确保了一定的顺序,但HashMap
没有。
如果你真的想知道内部发生了什么,请查看HashMap
的源代码 - 你可以在JDK安装目录下找到src.zip。
HashMap
有许多“桶”,用于存储其条目。一个条目存储在哪个桶中取决于条目键的哈希码。在HashMap
中看到条目的顺序取决于键的哈希码。但是不要编写依赖于HashMap
中的条目以某种顺序出现的程序 - 实现在Java的将来版本中可能会更改,然后你的程序将无法工作。
哈希表的元素没有明确定义的顺序
哈希表中没有定义的顺序。键根据哈希码放入一个槽中,但即使如此,这也不是一种简单的哈希码排序。
HashMap使用键的一部分生成唯一的哈希值来存储值。这个哈希值映射到它将要存储的地址。这就是它如何确保O(1)的访问。
另一方面,LinkedHashmap保留了您添加到映射中的顺序。