java HashMap浅析

一、什么是HashMap?

HashMap是java中一种很常用的数据结构(用来存放数据),HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中(数组中的每一个元素都是一个Entry键值对),这个数组就是HashMap的主干,如图:


对于HashMap最常用的操作就是get(根据key值获取value),put(将键值对存入HashMap)。

二、原理浅析

1.常用方法

一般在创建HashMap的时候会一起将泛型定义,定义泛型之后只能存取对应的数据类型的key-value(否则编译器会报错)


HashMap<String,Object> hashMap = new HashMap<String,Object>();
		hashMap.put("数学", 99);
		hashMap.put("语文", 90);
		hashMap.put("英语", 92);

这里我们模拟将三科的成绩存入新建的HashMap,接下来就可以调用get获取对应的key的value值


2.原理浅析

那么在调用put方法的时候发生了什么?

当运行hashMap.put("数学", 99),会插入一个key为数学value为99的键值对,这时候会利用一个哈希函数来确定键值对的插入位置(index )。

index =hash(“数学”);

假设index =2,结果就是:


Get方法的原理


使用Get方法根据Key来查找Value的时候,发生了什么呢?


首先会把输入的Key做一次Hash映射,得到对应的index:


index =  Hash(“数学”)


由于刚才所说的Hash冲突,同一个位置有可能匹配到多个Entry,这时候就需要顺着对应链表的头节点,一个一个向下来查找。假设我们要查找的Key是“数学”,这时候会拿着这个key去和每个键值对的key比较,如果相等,则返回对应key的value值


由于HashMap的长度是有限的(默认为16),当插入的键值对越来越多的时候,不同的key值通过hash函数运算出的结果可能出现相同的值,这时候就会产生链表


当有另外的键值对的hashcode值与原本hashMap中键值对的hashcode值重复时,就会产生如图的链表,新的entry键值对会放置在链表的头节点上。在日常开发中为了保证hashMap的快速存取,应当避免产生链表,当产生链表时,调用get方法效率会变低。

那么怎么避免产生链表呢?

hash函数的算法就是:(Length是HashMap的长度)利用每个键值对的key的HashCode与hashMap的长度进行位运算(&符号有兴趣可以百度一下原理)

index =  HashCode(Key) &  (Length - 1)

从公式上可以看出影响index的因素有两个,一个是key的HashCode,另一个是hashMap的长度。

(1)重写key类型的HashCode方法

class Student {
    String name;
    int age;
    //true表示男,false表示女
    boolean sex;


    @Override
    public int hashCode() {
        int result = 17;
        result = 37*result+name.hashCode();
        result = 37*result+age;
        result = 37*result+(sex ? 0 : 1);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Student &&
                this.name.equals(((Student)obj).name) &&
                this.age ==  ((Student)obj).age &&
                this.sex == ((Student)obj).sex;
    }
}
如果key的类型是String的话(String是继承Object类的final方法不能被重写),就不能重写了。

(2)改变hashMap的长度

1>初始化hashMap对象时可以设置长度

HashMap<String,Object> hashMap = new HashMap<String,Object>(1024);

长度应当为2的整数次幂(使hash方法结果分布均匀)

2>没有设置初始长度,会自动扩容


当hashMap中的元素数量达到长度的0.75倍时会自动扩容到原长度的2倍,然后重建hashMap,由于长度的变化,会重新运算原有键值对的index,会影响部分性能,如果要存放的元素数量较大时建议初始化时设置长度。





猜你喜欢

转载自blog.csdn.net/qq_40468795/article/details/80378366