以jdk7为例说明:
HashMap map = new HashMap();
在实例化以后,底层创建了一个长度为16的一位数组Entry[] table。
···可能已经执行过多次put操作了···
map.put(key1,value1)
首先会调用key1所在类的hashCode()方法计算key1的哈希值,然后通过某种算法计算出key1在Entry数组中的存放位置。
如果此位置上没有存放数据,则(key1-value1)添加成功。
如果此位置上有数据,则比较key1和已经存放的数据(一个或多个数据,其中多个数据是以链表的形式存储)的哈希值
如果key1的哈希值和已经存放的数据的哈希值都不相同,则(key1-value1)添加成功。
如果key1的哈希值和已经存放的某一个数据(key2-value2)的哈希值相同,则调用key1所在类的equals(key2)方法
如果equals返回false,则(key1-value1)添加成功。
如果equals返回true,则使用value1替换value2。
在不断添加的过程中:会涉及到扩容问题,当超出临界值时且要存放的位置非空时,默认情况下,扩容为原来的2倍,并把原来的数据复制过来。
jdk8中:
new HashMap():底层没有创建一个长度为16的数组。
jdk8底层的数组是:Node[],而非Entry数组。
首次调用put()方法时,底层去创建长度为16的数组。
jdk7底层结构:数组+链表。
jdk8底层结构:数组+链表+红黑树。
当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时此索引位置上的所有数据由数组+链表改为使用数组+红黑树存储,当数组的某一个索引位置上的元素以红黑树形式存在的数据个数<6时,此时此索引位置上的所有数据由数组+红黑树变为使用数组+链表存储。