为什么要hash?将对象转成int,在java中根据对象不同hash算法也不同。转成int方便在数组,链表中排列(hashcode)
为什么排列?怎么排列?(put)
正常情况下一个数组单元存一个数据,查找的时候一个个遍历查找就ok了
现在排列 通过负载因子(double常量<=1),减少单元数,这样就有更少的遍历和更快的查找,即用空间换取时间;
存在的问题:单元数减少,数据量增加,hash值相等概率上升,势必出现数据冲突
怎么解决:拉链法;即在原来的单元上再追加;
问题:出现冲突的数据怎么查找?
通过hash查找到一个新的链表,再遍历新的链表就ok;
存在问题:数据量大时,冲突数据越来越多,查询速度越来越慢;
解决方法:当数据量超过 (最大量(常量)*负载因子(常量)),将容量(常量)扩充一倍
当桶内数据超过8个,在jdk1.8中优化,将桶内链表变为红黑树结构
问题:怎么扩容rehashing?
新建一个容量更大的数组,拷贝原数组单元上的链表bucket,尾部变成头
为什么要扩大一倍:
优化散列,是数据均匀的分配在桶内
存在问题:在多线程下,2个线程操作链表都需要扩容时,会发生死锁;
解决:对所有操作方法添加同步锁synchronized
存在问题:完全加锁效率低下
解决:jdk1.7 使用分段锁 ,桶继承lock ,根据线程分段,然后再使用链表存储
jdk1.8 在判断桶时使用cas乐观锁,在链表中插入数据用synchronized
关于linkhashmap 在entry中多添加before ,after 维护数据顺序
关于treemap 根据key来排序
网友评论