获取数据时,也就是get方法,用hash(k)获取到hash值,然后结合长度获得数组下标,然后利用数组下标,按顺序遍历,利用equals方法比较获取v值
HashMap在存储数据时的流程?
HashMap在存储(k,v)时,会先利用hash(k)来计算出hash值然后利用数组长度来得出数组下标,然后这个hash值在HashMap是否存在,若不存在则直接插入,若存在则会发生碰撞,但是若equals返回true的话,就会改变其键值对,若equals返回false,则在尾部插入或者在树按顺序插入。
为什么HashMap的数组长度为2的幂次方?
HashMap为了高效存储,减少碰撞,所以将数据均匀分配,我们知道HashMap的存储范围前后加起来只有40多亿,但是如果现在有一个长度为40多亿的数组储存在HashMap中,则放不开了,所以HashMap就是将数组的长度取模后得到的余数来作为存储数据的位置也就是数组下标,但是HashMap的计算方式时hash&(n-1),只有n为2的幂次方时,hash&(n-1)才等价于hash%n,所以这也就是说明了为什么HashMap的数组长度为2的幂次方。
HashMap多线程容易造成死锁问题
这是因为在jdk1.7及之前HashMap的扩容机制都是在采用头插法这也就导致了,在多线程操作时,一个桶有多个元素进行扩容时,多个线程对一个链表进行操作,头插法的数据指向容易出错,从而出现环形链表,使得查询操作陷入死循环从而无法操作
所以在jdk1.8开始就使用了尾插法,这样当数据需要扩容时,直接在尾部插入即可从而避免了形成环形结构,但是还是建议在多线程下,尽量避免使用HashMap
HashMap与HashTable的区别
HashMap是线程不安全的,HashTable是线程安全的
正是因为HashTable的线程是安全的所以比HashMap的效率低
HashMap最多只允许一个键的内容为null,多个值为null而HashTable不允许
HashMap与HashTable到达扩容条件时HashMap为2n,而HashTable为2n+1;
HashMap需要重新计算hash值,HashTable直接用HashCode
HashMap ,LinkedHashMap与TreeMap的区别
HashMap的线程不安全的,最多只允许一个键的内容为null,多个值内容为null,当到达扩容机制时为2n
LinkedHashMap是有顺序的当遍历时,先遍历出的肯定是先存储的,然后就是遍历的比较慢
TreeMap使用SortMap接口的,能用他的键进行排列。