如何理解 List<T;和 Dictionary<K,V; 的扩容机制 ?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解 List<T;和 Dictionary<K,V; 的扩容机制 ?相关的知识,希望对你有一定的参考价值。
咨询区
Royi Namir
为什么 List
是按照 2倍
扩容。
private void EnsureCapacity(int min)
if (this._items.Length < min)
int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
if (num < min)
num = min;
this.Capacity = num;
而 Dictionary<K,V>
是按 素数
扩容。
private void Resize()
int prime = HashHelpers.GetPrime(this.count * 2);
int[] numArray = new int[prime];
for (int i = 0; i < numArray.Length; i++)
numArray[i] = -1;
Entry<TKey, TValue>[] destinationArray = new Entry<TKey, TValue>[prime];
Array.Copy(this.entries, 0, destinationArray, 0, this.count);
for (int j = 0; j < this.count; j++)
int index = destinationArray[j].hashCode % prime;
destinationArray[j].next = numArray[index];
numArray[index] = j;
this.buckets = numArray;
this.entries = destinationArray;
为什么不都按照 2倍
来呢?这样还可以实现代码复用。
回答区
Gman
Dictionary
是启发式的,它需要保证 hashcode
必须准均匀的分布在各个桶中,.NET 的 Dictionary
采用的是素数来实现这个均衡,下面是计算桶索引的算法。
int num = this.comparer.GetHashCode(key) & 2147483647; // make hash code positive
// get the remainder from division - that's our bucket index
int num2 = this.buckets[num % ((int)this.buckets.Length)];
不过 Java 采用的和 .NET 中的 List 是一样的扩容机制。
resize(2 * table.length);
在翻倍之后,java 会重新计算 hashcode 值的。
static int hash(int h)
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
static int indexFor(int h, int length)
return h & (length-1);
// from put() method
int hash = hash(key.hashCode()); // get modified hash
int i = indexFor(hash, table.length); // trim the hash to the bucket count
List 不是启发式的,所以没有这么烦恼,
点评区
其实说到底,Dictionary采用素数,本质目的就是减少桶挂链,减少hashcode冲突,如果挂链过长,那就达不到 Contains,Add,Get 等操作的 O(1)
时间复杂度,这也就失去了 Dictionary 原本的特性。
以上是关于如何理解 List<T;和 Dictionary<K,V; 的扩容机制 ?的主要内容,如果未能解决你的问题,请参考以下文章
java中private list<customer> customers;的<customer>是啥意思如何理解
IEnumeration<T> 和 List<T> 之间的区别? [复制]