剖析ArrayList和LinkList

存储方式

ArrayList

采用数组的方式进行存储
它实现 List 接口、底层使用数组保存所有元素。其操作基本上是对数组的操作,这个数组的内存是连续的,不存在相邻元素之间还隔着其他内存
但是arraylist存放的元素引用是连续的,引用指向的对象不是连续的,可能分散在不同的堆内存空间中

LinkList

双向链表: 每个节点上有两个指针(item/prve/next) 链表中的每一个元素称之为节点,节点在运行时动态生成 存储数据的数据域 存储下一个节点地址的指针域

扩容机制

ArrayList

add(Object o) 首次扩容为 10,再次扩容为上次容量的 1.5 倍
首次扩容会从0扩容成10,再次扩容会扩容到上一次容量的1.5倍,比如0,10,15,22,33…….

  • 首次扩容会从0扩容成10,然后把添加到容量为0的数组中,然后长度为10的数组的替换长度为0的数组,然后丢弃数组为0的数组
  • 第二次扩容会扩容到上一次容量的1.5倍,1.5倍指的是:先求扩容前容量的一半,然后再加入扩容前的容量===> 10>>1=5 ; 5+10=15

addAll(Collection c) 没有元素时,扩容为 Math.max(10, 实际元素个数),有元素时为 Math.max(原容量 1.5 倍【即扩容后的容量大小】, 实际元素个数)
list初始容量为0,然后调用addAll()进行扩容,首次扩容为容量是10,然后我们add 容量为11的数组,然后就会比较:Math.max(原容量 1.5 倍【即扩容后的容量大小】, 实际元素个数)>Math.max(10,11)=>11(两个数里面取较大的值)
数组list已经有10个元素了,然后再add(1,2,3) 3个元素,会调用addAll()进行扩容,然后就会比较:Math.max(原容量 1.5 倍【即扩容后的容量大小】, 实际元素个数)>Math.max(15,13)=>15
发现新增数据后,List的大小已经超过数组的容量的话,就会新增一个为原来1.5倍容量的新数组,然后把原数组的数据原封不动的复制到新数组中,再把新数组赋值给原来的数组对象就完成了

LinkList

linkedList 是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好。 扩容机制. (当前大小 和 当前容量 的比例超过了 扩容因子,就会扩容,扩容后大小为 一倍。 例如:初始大小为 16 ,扩容因子 0.75 ,当容量为12的时候,比例已经是0.75

适合查询的ArrayList

在查询时,LinkedList是从第一个开始一个个的往后对比查询的,如果查询一个消耗一秒,那查第n个数据时就要消耗n秒。
而ArrayList的底层由于是数组,所以他的内存空间是连续的,在查询时,可以根据下标直接查询对应位置的地址数
在这里插入图片描述

适合增删的LinkList

LinkedList丝毫不需要考虑有没有位置,若是想添加到第n个位置,则只需要把第n-1和第n+1之间的连接断开,插入这个数据,第n-1与n连接,n与n+1连接
在这里插入图片描述

内存空间占用比较

一般情况下,LinkedList的占用空间更大,因为每个节点要维护指向前后地址的两个节点,但也不是绝对,如果刚好数据量超过ArrayList默认的临时值时,ArrayList占用的空间也是不小的,因为扩容的原因会浪费将近原来数组一半的容量,不过,因为ArrayList的数组变量是用transient关键字修饰的,如果集合本身需要做序列化操作的话,ArrayList这部分多余的空间不会被序列化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值