对HashMap实现原理的理解

综合这几天网上查资料以及查看HashMap的源码,谈谈个人对HashMap底层的理解:

  • HashMap是一个散列集合,其底层是数组+链表结构,主体部分是个长度很长的数组.

    结构 :

    这里写图片描述

主体 : Entry数组(实际存key,value的对象);
链表 : 通过next方法指向链表下一个结点

  • 为了保证HashMap增删改查的效率,实质并上不是直接以key实例对象作为标识进行存值和取值,从put方法源码可以发现底层是获取key的hashCode值,经过异或运算和indexFor()方法运算得到的值作为标识,但由于hashCode的值并不唯一,经过运算获取的值也不能保证唯一(哈希冲突),所以,经过以上运算得来的数值只能作为数组的索引,当通过索引定位到这个节点时,在遍历该链表,判断是否存在相同的key对象,如果存在就用新的value覆盖旧的value
//HashMap部分源码

 public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }



       final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

hasCode知识点补充

一、hasCode概念

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值,对象通过调用hashCode()方法返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。

二、作用

对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode。在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合(无序集合)一起快速正常运行,使用hashCode的价值在于速度:运用hashCode作为标识使得查询得以快速进行.

三、使用: 拿String举例

  • 同一个对象

    public void test01(){
    
        String str1 = new String("123");
        String str2 = str1;
    
        int code1 = str1.hashCode();
        int code2 = str2.hashCode();
    
        System.out.println(code1);   ----->48690
        System.out.println(code2);   ----->48690
        System.out.println(str1.equals(str2));   ----->true
    }

  • 不同对象,相同内容

    public void test02(){
    
        String str1 = new String("aaa");
        String str2 = new String("aaa");
    
        int code1 = str1.hashCode();
        int code2 = str2.hashCode();
    
        System.out.println(code1);    ----->96321
        System.out.println(code2);    ----->96321
        System.out.println(str1.equals(str2));   ----->true
    }

    • 不同字符串对象,相同内容,生成的hashCode相同,明显String里面hashCode()方法明显是根据字符串内容生成的

    • 想要使hashCode()更实用,它必须速度更快,并且必须有意义,也就是说,它必须基于String对象的内容生成hashCode

    • 两个字符串对象用equals()方法比较返回true,因为String类重写了equals()方法,使得内容相同的两个字符串进行比较会返回true
  • 不同对象,不同内容

    public void test03(){
    
        String str1 ="Aa";
        String str2 ="BB";
    
        int code1 = str1.hashCode();
        int code2 = str2.hashCode();
    
        System.out.println(code1);  ---->2112
        System.out.println(code2);  ---->2112
        System.out.println(str1.equals(str2));   ---->false
    }

    • hashCode不必是独一无二的,更应该关注生成速度,而不是唯一性.
展开阅读全文

没有更多推荐了,返回首页