hashcode()方法 及 HashMap再分析

   之前 , 听过很多次,重写equals()方法的时候,必须重写hashcode() ,

   两个对象equals,hashcode()必然相等,两个对象hash值相等,当时不一定equals;

   那么 究竟hashcode 是什么?起的作用又是什么?

   hashcode() 和 equals() 方法都是Object(终极父类)中的方法;

   如果子类 没有重写 , 那么就默认的调用父类中的方法;

 

   Object 中的hashcode方法是通过本地方法实现的,并不是通过Java语言

public native int hashCode(); 
//This is typically implemented by converting the internal address of the object into an integer
//通过把对象的地址空间转换成一个整数实现的

   String 中的hashcode() :

 public int hashCode() {
        int h = hash;
// value 是 字符数组,字符串是一个字符数组构成的
        if (h == 0 && value.length > 0) {
            char val[] = value;
//散列公式: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

 

   hashcode的作用就体现在构建hashMap , hashtable 这种集合的时候;

   它们首先会根据对象hash值,找到相对应的数组下标,进行比较 , 插入和读取;

  如下面的hashmap中的get(Object key) 方法: 

 public V get(Object key) {
        if (key == null)
            return getForNullKey();
//hashmap通过拉链法处理冲突的,Entry是链表节点类型
        Entry<K,V> entry = getEntry(key); 
        return null == entry ? null : entry.getValue();
    }

 

final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }
// 看,这一步获取该key的hash值,hash(key)方法就调用key的hashcode方法
//所以,为什么我们自定义的类型做key都要重写hashcode方法,下面会告诉你
//为什么要重写equals()方法
        int hash = (key == null) ? 0 : hash(key);
// 根据hash值找到index , 然后就是遍历链表
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
//这里不就说明为什么要重写equals吗
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }

 

 final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }
     //这里不就是根据key的hashcode来生成相应的hash值
        h ^= k.hashCode();

        // 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);
    }

 关于HashMap的扩容?

  

void resize(int newCapacity) { 
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }
//新建一个新数组将容量扩大两倍
        Entry[] newTable = new Entry[newCapacity];
// 接下来就是怎样把原来数组的中的元素放入新数组中!       
        transfer(newTable, initHashSeedAsNeeded(newCapacity));
        table = newTable;
       threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }

    /**
     * Transfers all entries from current table to newTable.
     */
    void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
//对链表数组中的每个元素
        for (Entry<K,V> e : table) { 
//对链表中的每个元素
            while(null != e) {
                Entry<K,V> next = e.next;
                if (rehash) {
//对key可能要再次hash!!!
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
//根据e的hash值与数组的容量求的索引的位置!
                int i = indexFor(e.hash, newCapacity);
// 这一步的意思就是 前面可能有元素在i位置了,那么就把i位置的元素加在他后面!
                e.next = newTable[i]; 
                newTable[i] = e;
                e = next;
            }
        }
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值