HashMap是以Key-Value方式进行数据存储的一种数据结构 在JDK1.7和1.8底层数据结构不一样
1.7底层数据结构是:数组+链表 使用Entry类存储Key和Value 1.8底层数据结构是:数组+链表+红
黑树 使用Node类存储Key和Value 我们来看看Node类源码:
每一个节点都会保存自身的hash、key、和value以及下个节点 HashMap示意图:
HashMap本身的所有位置为null 所以在put操作时 回根据key的hash计算出一个index值 也就是这
个元素将要插入的位置
举个例子:比如 put(“小牛肉”,20),我插入了一个 key 为 “小牛肉” value 为 20 的元素,这个时候
我们会通过哈希函数计算出这个元素将要插入的位置,假设计算出来的结果是 2:
Node类里面定义了一个next属性 那么为什么需要链表?
首先 数组的长度有限 在有限的数组上使用哈希 会造成哈希冲突 很有可能两个元素计算的index是
相同的 那么如何解决Hash冲突?拉链法 就是把hash后值相同放在同一条链表 例如:
当然这里还有一个问题,那就是当 Hash 冲突严重时,在数组上形成的链表会变的越来越长,由于
链表不支持索引,要想在链表中找一个元素就需要遍历一遍链表,那显然效率是比较低的。为此,
JDK 1.8 引入了红黑树,当链表的长度大于 8 的时候就会转换为红黑树,不过,在转换之前,会先
去查看 table 数组的长度是否大于 64,如果数组的长度小于 64,那么 HashMap 会优先选择对数
组进行扩容 resize,而不是把链表转换成红黑树。
看下 JDK 1.8 下 HashMap 的完整示意图,应该画的比较清晰了:
1.hashCode():获取哈希码 equals():比较两个对象是否相等
2.二者两个约定:如果两个对象相等 他们必须有相同的哈希码 若两个对象的哈希码相同 他们却不
一定相等 也就是说 equal()比较两个对象相等时 hashCode一定相等 hashCode相等的两个对象
equals()不一定相等
3.加分回答:由于hashCode()与equals()具有联动关系 equals()重写时 hashCode()进行重写 使得
这两个方法始终满足相关的约定