数据结构-ArrayList-LinkedList--java进阶day09
1.数据结构
2.栈
详细流程:https://kdocs.cn/l/claZP6piLKDW?linkname=150996989
3.队
详细流程:https://kdocs.cn/l/claZP6piLKDW?linkname=150997055
4.数组
5.链表
1.双向链表
链表是由一个个的结点连接而成的,其中一个结点内部如下图所示
前一个结点会有下一个结点的地址,根据这个特点,结点会依次连接在一起
如果要查询一个数,就得从头开始查,因此链表的查询速度很慢
链表的增删速度很快,如下图
数据B将它的下一个地址指向C,而A将它的下一个地址指向B,这样就可以连接B这个结点
详细流程:https://kdocs.cn/l/claZP6piLKDW?linkname=150997082
2.双向链表
结点中即记录了下一个结点的地址,又记录了上一个结点的地址链接起来的链表就是双向链表
双向链表对于单向链表的好处在于,它既可以从头开始查询元素,也可以从尾开始查询元素,而不像单向链表只能从头开始查询
总结
6.ArrayList
1.ArrayList长度可变原理
之前聊过ArrayList长度可变的原理,如下图
但其实第一句话存在问题,实际上ArrayList如果只创建了容器,没有做添加操作的话,它的底层数组长度为0
我们进入到ArrayList的源代码中,发现一个空参构造
其中elementData是一个object类的数组
elementData这个数组纪录着一大串英文,我们点击这串英文,进入其内部
发现这串英文也是一个object类的数组,而且这个数组静态初始化,里面一个元素都没有,说明这个数组长度为0
java将这个长度为0的空数组赋值给了elementData数组
所以,当我们创建了ArrayList这个集合容器,没有进行添加操作的话,它的底层数组默认长度为0
接下来,我们再看使用了add方法,源代码会发生什么
首先,add方法将我们添加的元素装入了e中,然后add方法里面又调用了一个新的add方法
新的add方法将“abc”(e),还有长度为0的数组,以及集合长度(size)加入形参中
需要注意,size是成员变量,现在默认长度为0
接着,继续进入到新的add方法,方法将size=0赋给了s
然后s与elementData数组的长度进行比较,两者都为0,所以是true
所以,进入到grow方法,在grow方法中将size+1作为形参又传给了grow方法
然后,接着走新的grow方法
minCapability接收到size+1(1)
grow方法将数组长度(0)赋给了oldCapability,然后进行了一个if比较
很明显,oldCapability=0,是不可能大于0的,所以继续走后面的逻辑
elementData是一个空数组,DeFAultCAPCITY....也是一个空数组,逻辑给的是!=,明显不成立,所以走else
else中使用了Math类的一个找最大值的方法,其中DEFAULT大小为10
...
....
DEFAULT与minCapability(1)进行比较,很明显前者大,所以返回了10,因此完成了添加操作后,产生了长度为10的数组
总览
接下来,我们再来聊聊数组装满了10个元素,是怎么进行扩容的
我们添加第11个元素,add方法将新元素作为e传给新的add方法
接着走if判断,此时size=10,并且数组长度也为10,满足条件,走grow方法
如上图,假如还没装满10个元素,那就走红框的逻辑,添加元素进集合
grow方法将size变为11,并传给新的grow方法
oldCapability接收数组现长度(10),然后走if判断,明显10>0,接着走红框的逻辑
上图中,“>>”是表示除以2,10/2=5
如上图,红框中三个数作为实参传入newLength方法,调用newLength方法
如上图,newLength方法调用Math类的max方法,选取最大值(1和5中挑选),也就是5,再将oldCapability和选出来的数进行相加,然后赋值给preLength
接着进行一个判断,看preLength的范围是否满足大于0,小于SOFT...如果满足就返回preLength(15)
其中SOFT大小如下图,做这个范围的判断是为了限制数组大小不能无限大
ArrayList真实大小扩容原理,如下图
7.Linkedlist
1.添加
.
2.疑问
如图,添加了一些元素到LinkedList集合,因为LinkedList实现了List集合,所以可以使用List集合中根据索引来获取元素的get方法
...