Java哈希表
先引入哈希函数的概念:是对输入的某个key作为hash函数的输入 得到某个数字,将该数字作为数组的下标,将输入的值作为value进行存储。
但是有可能hash得到的值(hashcode)冲突,也就是所谓的哈希冲突,这时候就有几种处理方式,比如再散列,开放地址法,链地址法等等,在哈希表中采用的就是链地址法(数组+链表)。
哈希表
哈希表的主体是一个数组,数组的长度便代表了桶的个数,桶中存放的都是哈希值一致的Entry。哈希表的基本元素是Entry<key,value>.里面存储的是最重要的信息是键值对。
Entry是哈希表的一个内部类,代码如下
static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next;//存储指向下一个Entry的引用,单链表结构 int hash;//对key的hashcode值进行hash运算后得到的值,存储在Entry,避免重复计算 /** * Creates new entry. */ Entry(int h, K k, V v, Entry<K,V> n) { value = v; next = n; key = k; hash = h; }
链表是用来对产生哈希冲突的键进行处理的,理论上来说链表越少越好,因为对链表的查询时间复杂度为O(n),若没有哈希冲突时间复杂度为O(1)。
一些其他参数:
装填因子:表示当被填充的桶的个数与总桶数的阈值。当被填充的桶数大于这个值时,哈希表会进行resize,将自身的长度乘以2.
为什么哈希表的长度一般为2的幂次方
先了解一下得到数组索引的步骤
1.根据将key进行hash() 得到hashcode
2.hashcode&(length-1)得到数组索引
公式:当 length为2的幂次方时,hashcode&(length-1) = hashcode%length(通过这种方式能比较均匀地将hashcode进行分布)
而&的效率大于%,所以用将长度设为2^n比较好
浙公网安备 33010602011771号