HashTable如何计算数组下标

讨论源码环境为JDK1.8 211

HashTable如何计算数组下标?

首先我们看看String的hashCode是如何计算的(出自JDK1.8.0 211 java.lang.String 1452行—1476行)

/**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

String类重写了hashCode()函数,计算字符串的hashCode的公式为:
s [ 0 ] ∗ 3 1 n − 1 + s [ 1 ] ∗ 3 1 n − 2 + . . . + s [ n − 1 ] s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1] s[0]31n1+s[1]31n2+...+s[n1]
我们来举个例子:在这里插入图片描述
经过debug我们得知三个字符串的hashCode()返回值,我们来通过计算公式模拟一下:
字符串“a”,长度n=1,字符‘a’=97,代入公式得:
s [ 0 ] ∗ 3 1 n − 1 + s [ 1 ] ∗ 3 1 n − 2 + . . . + s [ n − 1 ] = 97 ∗ 3 1 1 − 1 = 97 s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1]=97*31^{1-1}=97 s[0]31n1+s[1]31n2+...+s[n1]=973111=97
字符串“ab”,长度n=2,字符‘a’=97,‘b’=98,代入公式得:
s [ 0 ] ∗ 3 1 n − 1 + s [ 1 ] ∗ 3 1 n − 2 + . . . + s [ n − 1 ] = 97 ∗ 3 1 2 − 1 + 98 ∗ 3 1 1 − 1 = 3105 s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1]=97*31^{2-1}+98*31^{1-1}=3105 s[0]31n1+s[1]31n2+...+s[n1]=973121+983111=3105
我们知道了String对象的hashCode是如何产生的了,接着我们看HashTable源码,看看它的数组下标是如何计算的:(代码截取自JDK1.8 211 java.util.HashTable.java 457行—479行)

public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

看这几行:

        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;

tab是HashTable底层的数组;
hash是key对象的hashCode();
index是通过key的hashCode()返回值计算出来的数组下标。
hashCode()返回值与2^31-1=0x7FFFFFFF(31位1)进行与(&)操作,然后除以数组长度取余,得到的就是下标值。

总结一下:HashTable计算数组下标值的时候,先获取key的hashCode()值(int类型),然后与int最大值进行与(&)操作,最后直接除以数组长度取余,得到数组下标。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值