一、HashMap的区别:
- 在jdk1.8中,当数组长度到达64,链表高度到达8时,会将链表转化成红黑树
- 链表结点由头插法改成尾插法,由于在jdk1.8中每次都要遍历结点,去判断链表的高度
- hash算法简化
- resize方法的逻辑修改(jdk1.7会出现死循环,jdk1.8不会)
二、ConcurrentHashMap的区别:
三: jdk1.7HashMap:
put() : 若key为null,则直接在数组下标为0的链表,若key不为null,先对keyhash,再对Hash进行与(table.length-1)进行与操作,得到数组下标,若table[i]为空,则table[i]=entry,不为空,则先遍历,已存在该key,覆盖,若不存在,则采用头插法,并使table[i]=该entry;
resize(): 当size大于阈值将扩容,在此时若有并发操作,会出现死循环。若正常扩容,则可以将原来的数据更加散列的放到新的扩容后的数组上。假设元素所在数组下标为i的链表上,原数组长度为length,则元素移动到新数组的下表为i或i+length。
get(): 若key不为null,则先对keyhash,在进行与操作,得到数组下标,遍历链表获取key所对应的value
四:jdk1.7ConcurrentHashMap:
put()方法中的scanAndLockForPut()方法:主要是为了获取锁资源,循环直至获取锁资源,其中retries变量初始为-1,若一直未获取锁资源,首先会进行链表的遍历,若链表遍历到结尾未发现已存在的key,则新建一个HashEntry,修改retries变量的值为0,进入另一个分支,若链表中找到了与当前插入的key相等,则也修改retries变量的值为0,也进入另一个分支,在另一个分支中,每次循环都会让retries变量自增,当达到某一值后,就会执行lock()方法,等待锁资源,不在循环,当retries变量为偶数时,会判断当前头结点是否与自己刚遍历时的头结点的key相同,若不相同,则表示有其它线程进行了put操作,则将retries修改为-1,重新进行第一分支的操作。
五: jdk1.8HashMap
- hash算法简化
- resize逻辑改变(不再会出现死锁问题)
- 当数组长度达到64,链表高度达到8是,链表转红黑树
- 由jdk1.7头插法改成尾插法
六: jdk1.8ConcurrentHashMap - 取消了segment字段,直接由table数组保存数据
- 由数组+单向链表变更为table数组+单向链表+红黑树。