基础篇-容器

文章详细介绍了ArrayList的扩容规则,初始为0,首次扩容为10,后续每次1.5倍增长。LinkedList的查询和插入性能特点,以及HashMap的实现原理,包括二次哈希解决冲突,链表转红黑树的策略,以及1.7和1.8版本的区别。同时提到了HashMap的线程安全问题和死链现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1.ArrayList扩容规则

知识点1:无参构造器的初始值为0

 知识点2:第一次扩容就会创建一个长度为10的数组
         第二次后扩容就会是上次的1.5倍(第二次数组长度就是10*1.5=15 
 注意:新的数组会代替旧的数组,旧的数组会被垃圾回收掉)

第二次扩容计算:
15>>1
7
15+7
22
前20次扩容的数组长度的打印:

addAll():
    1.list如果小于10,第一次扩容是10;
    2.扩容规则:下次扩容的大小和数组的长度中取较大值;

 

 总结:

 迭代器:

 

 

 

 failSafe:

 重复刚才的过程:

 **34-35 .FailFast源码分析

2.LinkedList

ArrayList:是基于内存存储连续存储 可以通过简单的计算可以算出内存地址
比如:第一个元素地址是0  每个地址都是30个字节   第四个下标的地址是:0+4*30=120
LinkList:比如也找到4,先从1找到2的地址,然后从2找到3的地址,从3找到4的地址;

 

 **36.04.00 -05.26 讲解源码

随机查询:AraryList性能更好

后面一样查询性能

LinkedList中间插入慢的原因:查找需要一个一个找到,极其消耗性能

ArrayList头部插入或者其他非尾部查询需要复制一份,然后进行数据替换,性能比较慢

 ** 38  空间占用原理讲解

3.HashMap

 3.1  HashMap的实现原理

计算原则:a 进行hashcode 97,然后二次hash得到 97 ,然后将97 和 数组长度16 进行取模得到1
这时候1就是a的下标

ArrayList获取a需要遍历查询,这种情况HashMap效率高的多

 3.2  链表过长的解决方案

链表过长的解决方案:
   1.扩容 当数组大于3/4被使用就会被扩容(数组长度是16的话,链表有13个元素就会被扩容 
   注意:扩容之后下标需要重新计算 如图1)
   2.红黑树  
   需要同时满足两个条件:1.链表长度大于8  2.数组容量必须大于64  如图2
   红黑树特点:是二叉树,左边小右边大,时间复杂度是O(logn),效率比链表高
   注意:链表查询的时间复杂度O(n) 链表(node)占用的内存没有红黑树(TreeNode)多
   正常情况下链表的长度不会大于8,主要防止黑客恶意攻击影响整个系统的性能 如图3
   红黑树何时退化成链表:
      

图1.

 图2.

 图3.

 图4.

 退化成链表:

 

 图5

3.3  索引是如何计算的

分布比较均匀的情况(正例):

 分布不均匀的情况(反例):

 原因:这些数据第一位都相同导致对16进行取模得到的数字都一样 解决方案:以jdk1.8为例 

 添加二次hash后,反例变均匀:

图6. 

 

 3.5 HashMap1.7和1.8的不同

 注意:扩容是添加完之后进行扩容

 

注意:1.7扩容的问题:扩容后遵循 头插法导致扩容之后顺序变了,这就会导致死链问题

           1.8在扩容计算node索引时,会优化:           

           按位与计算:如何是0则不用动位置,如果不为0则计算新的位置旧的位置+按位索引 

 3.6 HashMap负载因子的设计

 

注意:类型设置为Thread 

注意:多线程很有可能出现丢数据的问题,如上图这两个都有可能同时运行631行代码,导致前面的key被覆盖。 

 **p53.1.7死链

 

注意:1.字符串如果多个可以通过这个散列公式计算出对应的hashcode,得到足够混匀的hash值

           2.31优化更好可以用按位与进行运算 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值