HashMap的数据结构、实现原理、与HashTable的区别、jdk1.8优化
HashMap的数据结构
HashMap实际上是一个“链表散列”的数据结构,即由数组+链表组成,允许使用多个null值和一个null键,数组是HashMap的主体,链表是为了解决哈希冲突而存在的。
实现原理
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。当使用put(key,value)方法时,会计算出key的hash值,根据得到的hash值通过算法得到这个元素在数组中的位置,将元素储存在该位置上。当出现多个key的hash值定位到数组同一位置时则出现哈希碰撞,会在该位置上形成链表, 使用头插法(新加入元素放在链表头)将多个元素以链表形式储存。
与HashTable的区别
- HashMap是非线程安全的,HashTable是线程安全的。
- HashMap的键和值都允许有null值存在,而HashTable不允许。
- 但是因为HashTable的上锁机制,HashMap的效率要高于HashTable。
- 实际开发中则会用到ConcurrentHashMap(线程安全且效率较高)
如何实现HashMap的优化?
显而易见,如果HashMap中的链表数量少,HashMap对于增删改查操作都是极快的,所以对于HashMap的优化需要从减少哈希碰撞的出现几率下手。
- 因为key的hash值是通过hash算法计算的,所以算法的结果分散越均匀则哈希碰撞的次数越少。
- 而且HashMap的容量越大哈希碰撞的出现次数也会越少,所以根据实际情况进行合适的扩容也能减少哈希碰撞的出现次数。
JDK1.8对HashMap的优化
就算Hash算法和扩容机制再合理,也会出现链表过长的情况,会严重影响HashMap的性能。于是,在JDK1.8中,对HashMap的数据结构进行了进一步的优化。引入了增删改查都很快速的红黑树。当链表长度过长(默认为8),链表就换转换为红黑树。当链表长度变短(默认为6)时,将红黑树变回为链表。这样极大的提高了HashMap的性能。