ArrayList部分一共五篇文章了,而且引入了时间复杂度来分析,强烈建议你们必定要按顺序阅读,相关文章分别是:数组
一、ArrayList初始化 - Java那些事儿专栏源码分析
二、ArrayList底层数组扩容原理 - Java那些事儿专栏post
三、时间复杂度 - Java那些事儿专栏debug
五、ArrayList的时间复杂度 - Java那些事儿专栏(本文)cdn
在之前的文章里,咱们已经看过了add方法的源码,还有一个add方法,咱们看一下, public void add(int index, E element) ,从指定位置添加元素对象
按照下标把元素添加到指定位置,想必你们都知道,咱们直接上源码。blog
老规矩,咱们仍是画一画,当执行到System.arraycopy()这个方法时内存
我看到有些书上写的是依次移动元素到下一格,这种说法不够严谨,因此我再强调一遍,是依次复制插入位置及后面的数组元素,到后面一格,不是移动,所以,复制完后,arr[2],arr[3]指向对一个对象。element
在代码执行完这一句
咱们debug验证一下。
最后,在堆内存中建立李莫愁这个对象,把arr[2]的引用指向它。
再debug一下
最后咱们来讲说ArrayLIst这个对象里添加的时间复杂度:
若是咱们不指定位置直接添加元素时(add(E element)),元素会默认会添加在最后,不会触发底层数组的复制,不考虑底层数组自动扩容的话,时间复杂度为O(1) ,在指定位置添加元素(add(int index, E element)),须要复制底层数组,根据最坏打算,时间复杂度是O(n)。
最后咱们说一说读取元素,下面代码是获取List中下标为2的元素
看一下源码:
很简单,读取元素和数组长度无关,直接从底层数组里去拿元素。
评论区有人说,为何是“李莫愁”,看样子是不太喜欢“李莫愁”,咱们能够调用 set(int index, E element)方法来替换。
咱们看一看这个方法的源码
很简单,就是往指定位置放入元素,并返回原来的元素,最后咱们来画一画
图中“李莫愁”已经没有引用指向它了,JVM会在合适的时候回收它,底层数组第2个位置已经换成了“小龙女”,咱们debug验证一下。
没错,已经换成小龙女了。
这是最后一期ArrayLIst源码分析,引入了时间复杂度,最后,咱们来作个总结:
根据前几篇文章咱们能够看出来,在ArrayList中,底层数组存/取元素效率很是的高(get/set),时间复杂度是O(1),而查找,插入和删除元素效率彷佛不过高,时间复杂度为O(n)。
当咱们ArrayLIst里有大量数据时,这时候去频繁插入/删除元素会触发底层数组频繁拷贝,效率不高,还会形成内存空间的浪费,这个问题在另外一个类:LinkedList里有解决方案,请期待后续文章讲解。
查找元素效率不高,在HashMap里有解决方案,请关注后续文章。
下一篇:Arraylist与Vector的区别 - Java那些事儿专栏
注:本专栏文章首发于公众号:saysayJava。全部示例代码均已上传至公众号,须要请关注下载。
若是喜欢本系列文章,请为我点赞或顺手分享,您的支持是我继续下去的动力,您也能够在评论区留言想了解的内容,有机会本专栏会作讲解,最后别忘了关注一下我。
转载无限欢迎,但请注明「做者」和「原文地址」。转载请在文中保留此段,感谢您对做者版权的尊重。如需商业转载或刊登,请联系做者得到受权。