一、需求
以“key-value”的形式进行插入、查询、删除,是否可以考虑牺牲空间换时间的做法?
二、相关知识
哈希表(Hashtable)又称为“散列表”,Hashtable是会根据索引键的哈希程序代码组织成的索引键(Key)和值(Value)配对的集合。Hashtable 对象是由包含集合中元素的哈希桶(Bucket)所组成的。而Bucket是Hashtable内元素的虚拟子群组,可以让大部分集合中的搜寻和获取工作更容易、更快速。[1]
哈希函数(Hash Function)为根据索引键来返回数值哈希程序代码的算法。索引键(Key)是被存储对象的某些属性值(Value)。当对象加入至 Hashtable时,它存储在与对象哈希程序代码相符的哈希程序代码相关的Bucket中。当在Hashtable内搜寻值时,哈希程序代码会为该值产生,并且会搜寻与该哈希程序代码相关的Bucket。例如,student和teacher会放在不同的Bucket中,而dog和god会放在相同的 Bucket中。所以当索引键是唯一从Hashtable获取元素的性能时表现会较好。[1]
哈希表的优势体现在于空间换时间上,在设计哈希表时需要注意以下情况[2]:
1)Hash函数的选择,一个好的哈希函数可以均匀地将数据样本散列到表中;
2)冲突的解决方法,常用的冲突处理就是拉链法,即出现冲突时以链表的形式扩展;
3)表大小与关键字个数的平衡,设表大小为M,关键字个数为N,当装填因子(k=N/M)越大则冲突越严重;
三、源码实现
先放一个图例,Hashtable由多个Bucket组成,Bucket以HashKey值为索引,每个Bucket中存放着所有HashKey相同的(Key, Value)
如图所示,BucketNum = 5, DataNum = 7, 可见 k = 1.4 有一些冲突,更能很好地看出拉链法是如何解决冲突问题的:
如Key=A Key=E Key=F 算出来的 HKey 均为1,所以(A, ValueA) (B, ValueB) (C, ValueC)