关于ArrayList的源码关注点

1.从底层数据结构,扩容策略
2.ArrayList的增删改查
3.特殊处理重点关注
4.遍历的速度,随机访问和iterator访问效率对比

1.从底层数据结构,扩容策略

对于第一个问题,底层即时一个object的数组,用来存放动态数据:
transient Object[] elementData;
默认初始容量大小是10个,注意这里有个坑不是一开始就是10个,而是当进行add操作的时候,会默认修改为10个:private static final int DEFAULT_CAPACITY = 10;

源码中进行初始化的时候:

而我们的DEFAULTCAPACITY_EMPTY_ELEMENTDATA这个数据是,也就是说只进行new操作的时候,我们是给了一个空的数组大小是0长度是0,大小是0
Private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

这里源码中有一段代码:

collection.toArray()應該等同於collection.toArray(new Object[0]),返回的是Object[]類型。然而,Arrays.asList卻不是這樣,如果它的類型是一個Object[]子類(比如String[]),那麼toArray()就會返回這個子類而不是Object[],因為它調用的是clone())

作者:楊寒
链接:https://www.zhihu.com/question/26603565/answer/33394672
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

EnsureCapacityInternal 扩容策略最终调用======》grow方法进行大小增长

只有在容量不够了的时候才会采取扩容措施

private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

1.而且扩容也很简单粗暴,直接扩大1.5倍,采用右移的方式进行扩容,然后加上原始容量
2.如果括了1.5倍,还是比需要获取的大小要小,那么就直接把大小扩为想要获取的大小
3.如果扩容之后的大小,超出限制(Integer.MAX_VALUE - 8;),那么就扩到最大Integer.MAX_VALUE,如果期望的大小还没超过这个Integer.MAX_VALUE - 8;那么就扩围Integer.MAX_VALUE - 8;

最后吧新的数据拷贝过来取代旧数据

2.ArrayList的增删改查

2.1 add操作

进行add操作的时候支持2种添加方式

添加的时候size+1,作为新的size,然后调用扩容策略
最后吧新数据放到最后一个位置,返回true

其次添加到指定位置
做了2次拷贝操作
1.先创建新的容纳大小的空间
2.然后把需要添加进去的数据的index位置,往后推移拷贝一遍,然后再指定位置写入
System.arraycopy(elementData, index, elementData, index + 1,
size - index);

2.2 删除remove(obj),remove(int),fastRemove

Remove(obj)删除操作底层调用的还是fastremove
根据要删除的位置计算需要移动的元素个数

比如2个元素,现在要删除第一个元素,那么index=0,那么就是2-0-1 = 1;需要移动一个
Index就是对应的元素的下标,numMoved就是需要移动的元素的个数

直接删除索引
Remove(int)

删除这个索引之前,会先判断是否越界

和之前的删除大同小异

修改,查询就不说了,就是set和get操作,分别是elementData[index] = ele,和return elemenetData[index]

3.特殊处理重点关注,iterator

1.这里注意ArrayList有一个modCount属性,这个属性用来标识这个list被修改了多少次
2.注意使用迭代器的时候,对元素的增加或者删除,请用迭代器的删除,而不能用list的remove,而且遍历的时候只能删除,不能做新增

这个方法会校验

ExpectedModCount 而这个参数在创建iterator的时候,就进行了赋值 int expectedModCount = modCount;

4.遍历的速度,随机访问和iterator访问效率对比

并没有差别,其实iterator也就是对数组访问,所以不存在效率问题,只是我们一般的情况可以进行随机访问,而iterator只能进行遍历

5.是否支持多线程

这个就否了,不用管

借鉴:

https://www.zhihu.com/question/26603565
https://blog.csdn.net/fighterandknight/article/details/61240861

【数据结构】6.java源码ArrayList的更多相关文章

  1. java源码--ArrayList

    1.1.ArrayList概述 1)ArrayList是可以动态增长和缩减的索引序列,它是基于数组实现的List类. 2)该类封装了一个动态再分配的Object[]数组,每一个类对象都有一个capac ...

  2. Java源码系列1——ArrayList

    本文简单介绍了 ArrayList,并对扩容,添加,删除操作的源代码做分析.能力有限,欢迎指正. ArrayList是什么? ArrayList 就是数组列表,主要用来装载数据.底层实现是数组 Obj ...

  3. 如何阅读Java源码 阅读java的真实体会

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心.   说到技术基础,我打个比 ...

  4. 如何阅读Java源码

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动.源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧, ...

  5. Java 源码学习线路————_先JDK工具包集合_再core包,也就是String、StringBuffer等_Java IO类库

    http://www.iteye.com/topic/1113732 原则网址 Java源码初接触 如果你进行过一年左右的开发,喜欢用eclipse的debug功能.好了,你现在就有阅读源码的技术基础 ...

  6. [收藏] Java源码阅读的真实体会

    收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我 ...

  7. 如何阅读Java源码?

    阅读本文大概需要 3.6 分钟. 阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃< ...

  8. Java源码阅读的真实体会(一种学习思路)

    Java源码阅读的真实体会(一种学习思路) 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈 ...

  9. Java源码阅读的真实体会(一种学习思路)【转】

    Java源码阅读的真实体会(一种学习思路)   刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+ ...

随机推荐

  1. go语言Mac下编译安装语言包

    这两天公司成立了go语言学习兴趣小组,慕名参与了学习.目前对于go是0基础,只知道它可以做高并发.效率快.编译简单.母语是C. go的安装有多种形式,编译安装是比较慢的一个,今天我就记录一下学习go编 ...

  2. python 判断元素是否在一个列表中

    import random val= data=[,,,,] : find=False val=int(input('请输入查找键值(1-9),输入-1离开:')) for i in data: if ...

  3. vue使用案例,vue初始化,vue初始化方法,vue条件语句,vue在js里面添加元素调用vue方法

     <div id="main" > <button id='but1' type="button" v-on:click="save ...

  4. Logback的基本使用方法

    一.Logback简介 Logback是由log4j创始人设计的又一个开源日志组件. 1.logback当前分成三个模块:logback-core,logback- classic和logback-a ...

  5. Java String.split()函数分隔回车注意事项

    作者:Sun1956 原文:https://blog.csdn.net/sun1956/article/details/45096117 --------------------- 我们在Java中如 ...

  6. leetcode 494. 目标数

    题目描述: 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面. 返回可以 ...

  7. 剑指offer:把数组排成最小的数

    题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路分析: ...

  8. Python10大热门项目

    文章地址:https://baijiahao.baidu.com/s?id=1625230403885659615&wfr=spider&for=pc 今天给大家盘点一下实验楼最热门的 ...

  9. 对数损失函数logloss详解和python代码

    python机器学习-乳腺癌细胞挖掘(博主亲自录制视频)https://study.163.com/course/introduction.htm?courseId=1005269003&ut ...

  10. spring的multipartResolver和java后端获取的MultipartHttpServletRequest方法对比

    这两天在用spring进行上传上遇到问题,今天进行了问题的排查,这个过程也增加了我看spring源码的兴趣!还是很有收获的! 首先先给A组提供了上传接口,并没有在spring的配置文件进行multip ...