为什么Hashmap在内部使用LinkedList而不是Arraylist

时间:2015-06-20 18:51:50

标签: java data-structures hashmap

当两个对象放在哈希表的同一个存储桶中时,为什么Hashmap在内部使用LinkedList而不是Arraylist

3 个答案:

答案 0 :(得分:13)

  

为什么HashMap内部使用s LinkedList而不是Arraylist,当两个对象放在哈希表的同一个桶中时?

实际上,它也没有使用(!)。

它实际上使用通过链接哈希表条目实现的单链表。 (相比之下,LinkedList是双重链接的,并且它需要为列表中的每个元素分别使用Node个对象。)

那我为什么要在这里挑剔呢?因为它实际上很重要...因为这意味着LinkedListArrayList之间的正常权衡不适用。

正常的权衡是:

  • ArrayList占用的空间较少,但在最糟糕的情况下,所选元素的插入和移除为O(N)

  • LinkedList占用的空间更多,但所选元素的插入和移除为O(1)

但是,对于通过将HashMap条目节点链接在一起形成的私有单链表,空间开销是一个引用(与ArrayList相同),插入节点的成本为{ {1}}(与O(1)相同),删除所选节点的费用也是LinkedList(与O(1)相同)。

完全依赖"大O"对于这种分析是可疑的,但是当你查看实际的代码时,很明显LinkedList在删除和插入的性能上击败了HashMap,并且与查找相当。 (这忽略了内存局部效应。)并且它使用的内存比使用ArrayListArrayList的内存少......考虑到已经有内部条目对象来保存键/值对

但它变得更加复杂。在Java 8中,他们对LinkedList内部数据结构进行了全面检查。在当前实现中,一旦哈希链超过特定长度阈值,实现就切换到使用按键值排序的数组,以及用于链内查找的二进制搜索。那时,哈希链真的更好地被视为集合而不是列表。基于如何添加条目的哈希链的任何残留排序都将丢失。 (没关系。无论如何它都没有意义或稳定。)

答案 1 :(得分:0)

简短答案:Java使用LinkedList或ArrayList(以其认为适合于数据的形式为准)。

长期回答

尽管经过排序的ArrayList看起来很明显,但是改用LinkedList有一些实际的好处。 我们需要记住,仅当键冲突时才使用LinkedList链。 但是作为哈希函数的定义:冲突应该很少见

在极少数情况下,我们必须在Sorted ArrayList或LinkedList之间进行选择。 如果我们比较排序的ArrayList和LinkedList,则有一些明显的权衡点

  1. 插入和删除:排序的ArrayList取O(n),但LinkedList取常量O(1)
  2. 检索:已排序的ArrayList占用O(logn),LinkedList占用0(n)。

现在,很明显,LinkedList在插入和删除期间比排序的ArrayList更好,但是在检索时却很糟糕。

在冲突更少的情况下,排序的ArrayList带来的价值更少(但开销更大)。 但是,当冲突更加频繁且冲突元素列表变大(超过特定阈值)时,Java会将冲突数据结构从LinkedList更改为ArrayList。

答案 2 :(得分:-2)

这基本上归结为ArrayList和LinkedList的复杂性。 在LinkedList中插入(当顺序不重要时)是O(1),只是追加开始。 在ArrayList中插入(当顺序不重要时)是O(N),遍历到结尾,并且还有调整大小的开销。

删除是LinkedList中的O(n),遍历和调整指针。 arraylist中的删除可以是O(n ^ 2),遍历元素和移位元素或调整Arraylist的大小。

在任何一种情况下,包含都是O(n)。

使用HashMap时,我们期望O(1)操作可以添加,删除和包含。使用ArrayList,我们将在存储桶中添加,删除操作会产生更高的成本