hashMap的特性,无序,不重复
hashMap的底层数据接口 数组+链表
hashMap的加载因子0.75
hashMap的初始大小16
put方法
当我们声明一个hashMap的时候,并且往该map中put元素的时候,
HashMap map = new HashMap();
map.put("hundred",100)
hashMap首先将k,v封装到Node对象当中(节点)。
然后会调用key的hashCode方法算出hash值,然后根据哈希算法算出该key要存放的数组的下标,
这时候会出现两种情况 1 该数组下标处没有元素,则直接将该Node存放到该下标的数组中;2改数组下标处有元素,则会调用该元素的key的equals方法与要放入元素的key对比,如果这两个key的equals返回false,则在该位置的单项链表上追加元素,如果这两个key返回true,则将覆盖该Node的value。如果这个链表上有多个元素,则会挨个对比。
扩容问题
hashMap的加载因子 0.75 即当hashMap的元素达到了总容量的百分之75就开始扩容,为什么不能达到百分之百在扩容,因为例如上图中一个map的总容量是9,这个时候已经放入了12个元素了,但是由于其中下标为8的元素一直没有hashCode算出的下标是8的元素放入进去,所以容量没有达到百分之百,就无法扩容,这就导致一个问题就是其他位置的元素的链表将会很长,而链表很长的情况就会导致该位置每增加一个元素就会与该位置的所有元素进行equals对比,效率很低。因此设置了一个达到百分之七十五的时候去扩容,目的是为了降低碰撞概率。那么可不可以将加载因子设置的更小呢?如果设置的太小,则浪费空间,在空间使用了一小部分的时候就扩容也是不划算的。一旦扩容,就会将所有元素进行重排,原本在同一个位置的链表中的元素也会重新进行hash计算,放在扩容后数组的其他位置
java8 数组+链表+红黑树
在java8的时候对hashMap做了升级改造,在原本基础上又增加了红黑树,即当整个hashMap的元素大于64,单个链表的长度大于8的时候,会将单个链表转为红黑树,此时除了添加操作,其他的操作都会提升效率,那么为什么添加操作会不如原来的快呢?原本的链表只需要在最后一个元素追加上新元素即可,而如果变成了红黑树,则需要判断节点大小