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比较好

 

posted @ 2020-11-28 15:42  Coder_Dai  阅读(197)  评论(0)    收藏  举报