经常用到ArrayList,知道和LinkedList的对比优缺点,但是没那么读过源码。
首先它继承了AbstractList,实现了List接口,RandomAccess接口(支持快速随机访问,查询快的标记接口),Cloneable接口,序列化接口。
初始化参数:

// 初始容量为10private static final int DEFAULT_CAPACITY = 10;// 空数组实例private static final Object[] EMPTY_ELEMENTDATA = {};//   默认空数组实例,区别于上面的就是第一个元素添加时候增长多少
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存储数组缓冲区,ArrayList的容量就是此数组的长度,第一个元素添加的时候,数组容量从0变10transient Object[] elementData;// 大小private int size;// ArrayList被修改的次数,初始值为0,来自父类protected transient int modCount = 0;//  最大容量,为2的31次方-1 ,再减8,除非有必要再使用,否则可能有些jvm会OutOfMemoryError报错private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

三个构造函数,不带参数,带容量大小参数,带集合参数:

// 创建指定容量的ArrayList
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {// 指定容量大于0,那么创建一个Object[initialCapacity]的数组this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 指定容量小于0,那么等于空数组实例this.elementData = EMPTY_ELEMENTDATA;} else {//   指定容量小于0,抛出异常 : IllegalArgumentExceptionthrow new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}// 不带参数的构造函数,创建一个容量为10的ArrayListpublic ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}// 参数为集合的构造函数,顺序为集合迭代器返回顺序public ArrayList(Collection<? extends E> c) {// 集合转换为数组elementData = c.toArray();//    如果数组大小不为0if ((size = elementData.length) != 0) {// 防止没有返回对象数组的错误if (elementData.getClass() != Object[].class)// 元素拷贝创建ArrayListelementData = Arrays.copyOf(elementData, size, Object[].class);} else {// 否则创建一个空ArrayListthis.elementData = EMPTY_ELEMENTDATA;}}

trimToSize()方法:压缩容量到实际大小

public void trimToSize() {// 修改次数+1modCount++;//  如果真实大小小于容量if (size < elementData.length) {// 当大小等于0时候为空数组elementData = (size == 0)? EMPTY_ELEMENTDATA// 当大小不等于0的时候复制真实数组: Arrays.copyOf(elementData, size);}}

确保容量方法ensureCapacity(int minCapacity)

public void ensureCapacity(int minCapacity) {// 如果参数minCapacity大于真实长度if (minCapacity > elementData.length&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA&& minCapacity <= DEFAULT_CAPACITY)) {// 增加修改次数modCount++;// 扩容grow(minCapacity);}}// 扩容成新的大小数组
private Object[] grow(int minCapacity) {return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));}// 计算新容量方法
private int newCapacity(int minCapacity) {// 老容量为真实长度int oldCapacity = elementData.length;// 新容量为老容量*1.5int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果新容量小于minCapacity,则返回minCapacityif (newCapacity - minCapacity <= 0) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)return Math.max(DEFAULT_CAPACITY, minCapacity);if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return minCapacity;}// 无参增长新容量private Object[] grow() {return grow(size + 1);}// 判断是否大于最大容量,小于的话返回新容量,大于的话直接返回最大容量return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity: hugeCapacity(minCapacity);}// 创建最大容量的静态方法
private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE)? Integer.MAX_VALUE: MAX_ARRAY_SIZE;}

size() 方法返回size

public int size() {return size;}

isEmpty() 方法返回是否为空

public boolean isEmpty() {return size == 0;}

contains(Object o) 方法返回是否包含某个对象

public boolean contains(Object o) {return indexOf(o) >= 0;}

indexOf(Object o) 方法返回第一个找到该对象的index,如果找不到 返回-1

public int indexOf(Object o) {// 从0位找到最后位return indexOfRange(o, 0, size);}// 找到对象从start到end之间的index,遍历数组int indexOfRange(Object o, int start, int end) {Object[] es = elementData;if (o == null) {for (int i = start; i < end; i++) {if (es[i] == null) {return i;}}} else {for (int i = start; i < end; i++) {// 判断两个值是否相等,相等返回if (o.equals(es[i])) {return i;}}}return -1;}

lastIndexOf(Object o) 方法,找到最后一个该对象的index,没有则-1

// 同上,从尾部开始遍历,返回
public int lastIndexOf(Object o) {return lastIndexOfRange(o, 0, size);}int lastIndexOfRange(Object o, int start, int end) {Object[] es = elementData;if (o == null) {for (int i = end - 1; i >= start; i--) {if (es[i] == null) {return i;}}} else {for (int i = end - 1; i >= start; i--) {if (o.equals(es[i])) {return i;}}}return -1;}

clone() 方法,返回一个浅拷贝,元素本身不会被复制

 public Object clone() {try {ArrayList<?> v = (ArrayList<?>) super.clone();// 调用Arrays中的copyOf方法v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {throw new InternalError(e);}}// 以下为Arrays中的方法
public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;}//以下为System中的arraycopy方法public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

toArray()方法,返回一个包含所有元素的数组

public Object[] toArray() {return Arrays.copyOf(elementData, size);}
public <T> T[] toArray(T[] a) {if (a.length < size)// Make a new array of a's runtime type, but my contents:return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;}

get(int index)方法,返回index元素

 public E get(int index) {Objects.checkIndex(index, size);return elementData(index);}E elementData(int index) {return (E) elementData[index];}// 以下为Objects的方法,检查index是否在范围内public static int checkIndex(int index, int length) {return Preconditions.checkIndex(index, length, null);}//以下为Preconditions的方法,如果index在范围外则抛出outOfBoundsCheckIndex异常public static <X extends RuntimeException>int checkIndex(int index, int length,BiFunction<String, List<Integer>, X> oobef) {if (index < 0 || index >= length)throw outOfBoundsCheckIndex(oobef, index, length);return index;}

set(int index, E element)方法,修改指定index处的值,并返回旧值

public E set(int index, E element) {// 检查index范围Objects.checkIndex(index, size);// 得到旧值E oldValue = elementData(index);// 更换新值elementData[index] = element;// 返回旧值return oldValue;}

add(E e) 方法,在list末尾加上e,返回boolean

 public boolean add(E e) {modCount++;add(e, elementData, size);return true;}private void add(E e, Object[] elementData, int s) {if (s == elementData.length)// 扩容elementData = grow();elementData[s] = e;size = s + 1;}

add(int index, E element)方法,指定index位置插入值,并且当前和之后受影响元素后移,无返回值

public void add(int index, E element) {// 检查index是否在范围内,不在的话抛出IndexOutOfBoundsException异常rangeCheckForAdd(index);modCount++;final int s;Object[] elementData;if ((s = size) == (elementData = this.elementData).length)elementData = grow();System.arraycopy(elementData, index,elementData, index + 1,s - index);elementData[index] = element;size = s + 1;}private void rangeCheckForAdd(int index) {if (index > size || index < 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}

remove(int index)方法,返回被移除对象

    public E remove(int index) {Objects.checkIndex(index, size);final Object[] es = elementData;E oldValue = (E) es[index];fastRemove(es, index);return oldValue;}private void fastRemove(Object[] es, int i) {modCount++;final int newSize;if ((newSize = size - 1) > i)System.arraycopy(es, i + 1, es, i, newSize - i);es[size = newSize] = null;}

很多操作中都会出现的System.arraycopy数组复制方法,是一种native的方法

 public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

参数
src: 原始数组
srcPos:原始数组的起始位置
dest: 目标数组
destPos: 目标数组的起始位置
length: 复制元素的数量

clear()方法,清空,无返回值,循环设置null,size设为0

public void clear() {modCount++;final Object[] es = elementData;for (int to = size, i = size = 0; i < to; i++)es[i] = null;}

addAll(Collection<? extends E> c) 方法,添加集合,返回boolean

 public boolean addAll(Collection<? extends E> c) {// 首先集合转对数组Object[] a = c.toArray();// 增加修改次数modCount++;// 获得对象数组长度int numNew = a.length;// 长度为0返回falseif (numNew == 0)return false;Object[] elementData;final int s;// 如果新增容量大于ArrayList的剩余容量则进行扩容if (numNew > (elementData = this.elementData).length - (s = size))elementData = grow(s + numNew);// 复制对象数组到ArrayList中System.arraycopy(a, 0, elementData, s, numNew);size = s + numNew;return true;}

addAll(int index, Collection<? extends E> c) 增加集合到数组中,从index开始,返回值为boolean,具体操作和上面差不多,只是起始位置,复制个数修改一下

public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);Object[] a = c.toArray();modCount++;int numNew = a.length;if (numNew == 0)return false;Object[] elementData;final int s;if (numNew > (elementData = this.elementData).length - (s = size))elementData = grow(s + numNew);int numMoved = s - index;if (numMoved > 0)System.arraycopy(elementData, index,elementData, index + numNew,numMoved);System.arraycopy(a, 0, elementData, index, numNew);size = s + numNew;return true;}

void removeRange(int fromIndex, int toIndex)方法,移除fromIndex和toIndex之间的元素,包括fromIndex但是不包括toIndex

protected void removeRange(int fromIndex, int toIndex) {// 判断参数是否正确if (fromIndex > toIndex) {throw new IndexOutOfBoundsException(outOfBoundsMsg(fromIndex, toIndex));}// 增加修改次数modCount++;// 内部方法移除shiftTailOverGap(elementData, fromIndex, toIndex);}private void shiftTailOverGap(Object[] es, int lo, int hi) {// 从toIndex开始之后的数组,移动到fromIndex位置开始System.arraycopy(es, hi, es, lo, size - hi);// 把容量之外的元素变成nullfor (int to = size, i = (size -= hi - lo); i < to; i++)es[i] = null;}

boolean removeAll(Collection<?> c) 方法,移除ArrayList中所有c中的元素

public boolean removeAll(Collection<?> c) {return batchRemove(c, false, 0, size);}boolean batchRemove(Collection<?> c, boolean complement,final int from, final int end) {// 检查不为nullObjects.requireNonNull(c);final Object[] es = elementData;int r;// 如果c中不包含ArrayList中的元素,那么直接返回false,否则向下执行,           同时r定位到第一个包含的位置for (r = from;; r++) {if (r == end)return false;if (c.contains(es[r]) != complement)break;}// w定位到r下一个位置int w = r++;try {for (Object e; r < end; r++)if (c.contains(e = es[r]) == complement)// 利用w指针记录如果c中包含的元素,那么就删除es[w++] = e;} catch (Throwable ex) {System.arraycopy(es, r, es, w, end - r);w += end - r;throw ex;} finally {modCount += end - w;// 移除w和end之间的元素shiftTailOverGap(es, w, end);}return true;}// Objects中如果对象参数为null则抛出异常的方法public static <T> T requireNonNull(T obj) {if (obj == null)throw new NullPointerException();return obj;}

ListIterator listIterator(int index)方法,返回一个list iterator, 从index处开始。

public ListIterator<E> listIterator(int index) {rangeCheckForAdd(index);return new ListItr(index);}

List subList(int fromIndex, int toIndex) 方法返回一个范围内的子类

public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList<>(this, fromIndex, toIndex);}

void writeObject(java.io.ObjectOutputStream s) 方法,序列化

private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioral compatibility with clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}}

void readObject(java.io.ObjectInputStream s)方法,反序列化

private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {// Read in size, and any hidden stuffs.defaultReadObject();// Read in capacitys.readInt(); // ignoredif (size > 0) {// like clone(), allocate array based upon size not capacitySharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);Object[] elements = new Object[size];// Read in all elements in the proper order.for (int i = 0; i < size; i++) {elements[i] = s.readObject();}elementData = elements;} else if (size == 0) {elementData = EMPTY_ELEMENTDATA;} else {throw new java.io.InvalidObjectException("Invalid size: " + size);}}

ArrayList中包含了四个内部类

 private class Itr implements Iterator<E> private class ListItr extends Itr implements ListIterator<E>private static class SubList<E> extends AbstractList<E> implements RandomAccessfinal class ArrayListSpliterator implements Spliterator<E>

更详细内容可以参考:link

鸟枪换炮读源码系列之ArrayList(java11)相关推荐

  1. Spring读源码系列之AOP--03---aop底层基础类学习

    Spring读源码系列之AOP--03---aop底层基础类学习 引子 Spring AOP常用类解释 AopInfrastructureBean---免被AOP代理的标记接口 ProxyConfig ...

  2. 带着问题读源码-soul(2021-01-16)

    ### 带着问题读源码系列之Dubbo插件 像往常一样启动 [soul-admin] 和 [soul-bootstrap] . 因为dubbo需要依赖zookeeper, 需要需要启动一个监听在 lo ...

  3. 微信读书vscode插件_跟我一起读源码 – 如何阅读开源代码

    阅读是最好的老师 在学习和提升编程技术的时候,通过阅读高质量的源码,来学习专家写的高质量的代码,是一种非常有效的提升自我的方式.程序员群体是一群乐于分享的群体,因此在互联网上有大量的高质量开源项目,阅 ...

  4. 带着问题读源码-soul(2021-01-15)

    带着问题读源码系列-soul的本地服务筛选 在上一期中,了解到soul的http请求是通过dividePlugin插件完成对本地服务的筛选. 总体来说,可以分为两步: 1. 选出符合调用要求的服务列表 ...

  5. java 源码系列 - 带你读懂 Reference 和 ReferenceQueue

    java 源码系列 - 带你读懂 Reference 和 ReferenceQueue https://blog.csdn.net/gdutxiaoxu/article/details/8073858 ...

  6. 我是怎么读源码的,授之以渔

    点击上方"视学算法",选择"设为星标" 做积极的人,而不是积极废人 作者 :youzhibing 链接 :https://www.cnblogs.com/you ...

  7. 学会读源码,很重要!

    刚参加工作那会,没想过去读源码,更没想过去改框架的源码:总想着别人的框架应该是完美的.万能的,应该不需要改:另外即使我改了源码,怎么样让我的改动生效了?项目中引用的不还是没改的jar包吗.回想起来觉得 ...

  8. 杂谈篇之我是怎么读源码的,授之以渔

    前言 开心一刻 今天上课不小心睡着了,结果被老师叫起来回答问题,这是背景.无奈之下看向同桌寻求帮助,同桌小声说到选C,结果周围的人都说选C,向同桌投去一个感激的眼神后大声说道选C.刚说完教室就笑开了, ...

  9. java源码分析之ArrayList

    ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么Arra ...

最新文章

  1. 《大道至简》第一章编程的精义伪代码读后感
  2. Terraform 多云管理工具
  3. spring boot 整合多数据源JDBC、多数据源mybatis、多数据源springdata jpa
  4. python内置函数用来返回数值型序列中所有元素之和_语句x = 3==3, 5执行结束后,变量x的值为_学小易找答案...
  5. 基于MPI的H.264并行编码代码移植与优化
  6. 在tomcat上全手工部署Servlet3.0
  7. ckeditor+ckfinder使用
  8. Windows 7 专业版如何安装英文、中文语言包
  9. 微型计算机原理与接口技术综述论文,微型计算机原理接口与技术综述论文汇编.doc...
  10. 全球上市公司和VC们如何布局元宇宙,是资本盛宴还是炒作概念?
  11. Dev-C++中, “\“反斜杠符号显示成人民币符号、中文斜躺 问题
  12. Linux页表查询--页表项、页面、页内偏移量
  13. 一个游戏建模师一天的工作都在做什么?
  14. 用html5设置国际象棋棋盘,绘制国际象棋棋盘
  15. 递归下降分析法实现强化计算器
  16. 微信公众平台针对欺诈等违规行为处理结果公示
  17. 为什么面试要问hashmap 的原理
  18. html生成日期表,如何从此HTML表格提取日期?
  19. Flask系列教程(一)-----------入门
  20. windows电脑安装python教程

热门文章

  1. java中写html标签,java写html剔出标签
  2. LeetCode 43. 字符串相乘【c++/java详细题解】
  3. visio添加外键约束
  4. 传统企业如何精准获客?搭上这趟高科技顺风车
  5. Unity添加自发光材质
  6. 什么是GPU加速,如何使用GPU加速,GPU加速的缺点
  7. 情人节快到了,我部署了一套情侣头像小程序,并过审了
  8. coreseek 词库 导入搜狗词库
  9. 计算机软件研究方法与技术路线,开题报告研究方法与技术路线.doc
  10. mysql8.0.21官网安装步骤_MySQL8.0.21安装步骤及出现问题解决方案