| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> Arraylist源码分析 -> 正文阅读 |
|
[数据结构与算法]Arraylist源码分析 |
一个大腹便便的身穿格子衫的秃头老,缓缓的想你走来,心想看到这头秃的,就几根了,怎么也得顶级架构师吧!但是咱也是看过源码的人,不虚他!那么我们就开始今天的ArrayList旅程把! 小伙子,今天我就来考考你ArryList,看看你到底是骡子是🐎! 好嘞,那今天就看我的表现吧!(尼玛,你才是骡子,老子是🐎)! 秃头老:ArrayList知道吧,工作中经常用的集合,你来简单的介绍一下 我:首先ArrayList底层是用Object[]数组来实现的,可以实现动态增长;其次通过看源码我们可以得知它继承了AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable,其中List代表他是一个集合,RandomAccess是支持快速随机访问,Cloneable覆盖了clone方法,能被克隆,Serializable代表可以进行序列化传输。 秃头老:那你知道ArrayList和Vector的区别吗?(哎呦小伙子,还看过源码呀,来来接着靠你,不考到你不会,今天就不结束!) 我:ArrayList和Vector都是List的实现类,底层都是Object[]数组实现的,区别就是ArrrayList是线程不安全的,而Vector是线程安全的! (这才哪跟哪,给我整点难的!) 秃头老:那你再说说ArrayList和LinkedList的区别! 我:(劳资给你分点说,让你看看有多细!) 1、从底层实现上来说,A(ArrayList)是通过Object[]存储的,L(LinkedList)是通过双向链表存储的(JDK1.6是循环链表,JDK1.7就变成了双向链表) 2、从线程安全性来说,A和L都是线程不安全的! 3、从快速随机访问来说,A是支持快速随机访问的,L不支持,相当于遍历数组 4、从插入删除是否受位置影响来说,A如果在末尾插入删除时间复杂度为O(1),如果在第i个位置插入删除,则需要移动元素,时间复杂度为O(n-i),L在末尾插入和删除都是O(1),如果**指定位置的话是O(n)**需要先查找在插入删除! 5、从内存空间占用来说,A浪费主要在结尾都有一部分的预留空间,L主要是每个元素都比A占的空间大,因为需要直接前驱和直接后继! 秃头老:小伙子,看来确实是做过一些功课呀,那既然你看过源码,说说ArrayList的构造函数吧(老子要给挖坑了,准备给我跳进去!) 我:(TM的想问扩容机制,我早看透了!) 构造函数有两种,一种是无参构造,一种是有参构造。无参构造的话默认是赋值一个空对象,只有添加第一个元素的时候才会初始化容量为10的数组;有参构造有两个,一种是指定数组大小的,根据数组大小来初始化A,一种是传一个集合,把集合添加到数组中! 哝,来瞅瞅源码!
秃头老:既然你知道默认无参构造只有添加元素的时候才会初始化容量为10的数组,那它是什么实现的那? 我:(C)这个就说来话长了,那我们首先需要知道三大方法ensureCapacityInternal(int minCapacity),ensureExplicitCapacity(int minCapacity),grow(int minCapacity),我们从add(E e)方法说起
很简单,先调用了ensureCapacityInternal(size + 1),当我们第一次添加元素的时候参数为size+1=1。
通过上面不难看出,因为第一次添加元素的时候elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA为true,就会把DEFAULT_CAPACITY(10)和minCapacity(1)来比较,从而返回10,这就把数组大小定了。
此时minCapcity为10,elementData.length为0(空list,第一次添加),符合条件则进行扩容,我们在想当第二次添加的时候minCapacity为2,所以不会进行扩容,知道添加第11个元素的时候才会扩容!
通过grow我们看出每次扩容1.5倍,当第一次添加的时候,oldCapacity = 0,newCapacity = 0,newCapacity - minCapacity < 0(0 -10)成立,所以newCapacity为10。 补充:
简单的来说,就是当添加第一个元素的时候,先调用ensureCapacityInternal判断是不是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,是的话则把minCapacity该为10,调用ensureExplicitCapacity来进行grow,如果第一次扩容则会把扩容大小为minCapacity(10)结束! 秃头老:还不错哦,小伙子,那你有没有发现源码中有引起你注意的方法?(小崽子有点东西哦!) 我:(MD,还问,扩容机制都给你讲的明明白白的了!) 确实有哦,源码中经常用到
我们再来看看使用场景(指定位置添加元素):
秃头老:(这小伙子肚子还是有点东西的!)那你有没有发现 我:(老东西,还TMD的问,没玩了,你给我等着哦!) 发现了哦,这个方法主要是为了当有大量数据插入的时候,先调用这个方法进行扩容,因为大量数据插入会递增式的调用扩容,这个是事先给我们扩容一个比较适合的大小,节省了大量时间!
举例说明:
参考文章:Guide哥的Java学习 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 16:25:46- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |