【无标题】111111111

 
 
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{

-- Cloneable: copy
-- Serializable: 网络传输,存盘,持久化,根据版本号反序列化


}

数组: 在内存中是连续的存储的单元。查询快,插入慢。

链表:查询慢,插入删除快。

hash算法:散列算法,把任意长度值的key通过散列算法变换成固定长度的地址。eg.MD5

hashCode: ASCII码

HashMap: 数组+链表+红黑树

why 数组?

没有哈希冲突时,用数组存放。

why 链表?

用来解决哈希冲突的问题,有哈希冲突,多个元素放在数组的同一个位置, 形成链表。

1.7以前 用头插法,在并发情况下,线程1 执行了空间扩容,读到的是A->B, 线程中断,线程2又进行了扩容,链表重排序,变成了B->A, 那么线程1读到的B指向的就是A,会发生死循环。

为了避免这种情况,1.8 改成了尾插法。

why 红黑树?

当哈希冲突的数据很多时, 链表很长,但链表查询只能从第一个元素开始遍历查找,效率很低,因此当长度>8时,会转换成红黑树, 以提高查询效率。

HashMap -- Put 过程:

根据key计算hash,

数组是否为空 -- 如果为空,创建数组。

resize创建数组table并设置容量(16),加载因子为0.75, 因此容量为12的时候,会进行扩容,链表的长度大于8-1时,会变成红黑树, 当删除元素使链表长度变为6,红黑树会转变回链表结构。

数组不为空,根据hash值确定在数组中的位置i(table)。

判断table[i]是否为空,如果为空,说明该位置还没有元素存入,直接插入数据。

如果table[i]不为空,说明该位置已经有数据,发生了hash冲突,比较哈希值和key值是否相等。

如果相同, 修改原值返回原值。

如果不相同:判断长度>8-1(是否是红黑树)。

如果是红黑树, 遍历红黑树,看是否存在,没有就直接插入,有的话修改替换。

如果是链表,遍历链表,链表里没有该值,在链表尾部添加,链表长度>8-1,转为红黑树。

concurrentHashMap 和HashTable  的put 方法上 加了 synchronized,线程安全。

Cas:线程状态不改变

Lock:线程状态 运行--》阻塞

线程切换

猜你喜欢

转载自blog.csdn.net/weixin_44969766/article/details/121566104