HashMap中Java7和Java8有什么区别呢?
下文笔者讲述HashMap中jdk1.7和jdk1.8的区别说明,如下所示
区别1:底层存储的数据结构区别
Java 7使用Entry数组+单链表的数据结构
Java 8使用Node数组+单链表+红黑树,使用此种存储结构,可将时间复杂度从O(n)变成O(logN),查询效率得到提高
区别2:Hash冲突解决方法不同
Java 7中采用头插法,新元素插入到链表头中,即新元素总是添加到数组中,旧元素移动到链表中
Java 8会优先判断该节点的数据结构式是红黑树还是链表
当是红黑树,则在红黑树中插入数据
当是链表,则采用尾插法,将数据插入到链表的尾部,然后判断是否需要转成红黑树
相关说明:
1.由于JDK7使用单链表进行的纵向延伸,当采用头插法时会容易出现逆序且环形链表死循环问题
JDK8之后是因为加入红黑树使用尾插法,能够避免出现逆序且链表死循环的问题。
2.头插法优点:
resize后transfer数据时不需要遍历链表到尾部再插入
区别3:扩容机制不同
Java 7:在扩容resize()过程中
使用单链表的头插入方式,在线程下将旧数组上的数据 转移到 新数组上时,容易出现死循环
此时(多线程)并发运行put()操作,一旦出现扩容情况,则容易出现环形链表,从而在获取数据、遍历链表时形成死循环(Infinite Loop)即死锁的状态。
Java 8:由于Java 8 转移数据操作 = 按旧链表的正序遍历链表、在新链表的尾部依次插入,所以不会出现链表 逆序、倒置的情况,故不容易出现环形链表的情况
区别4:扩容后存放位置不同
Java 7受rehash影响
Java 8调整后是原位置 or 原位置+旧容量
HashMap中使用经验
1.设置合适的初始值,避免出现扩容带来的性能消耗 2.如果使用自定义对象作为key,则需重写hashCode和equals方法 3.多线程下,笔者建议使用CurrentHashMap代替HashMap
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


