不出意外的话, ArrayList 这个集合,我们平常在写代码的时候,肯定是使用到非常多的。竟然我们使用了这么多,那我们是不是应该看下 ArrayList 这个类呢. 快上车,上了就别想下来了,车门都给你焊死hhhhh.

先来看下ArrayList的上级,可以看到最上面有一个迭代器,这个是不是想到了有一种设计模式叫迭代器设计模式?

这里,我们直接一步到位,点到源码里面来. 我们接下来就分析这几个我们经常在代码里面使用到的方法,看看这些方法是怎么实现的?

在我们new一个对象的时候,然后调用其方法,我个人认为在这之前,应该在去看一下这个对象的属性.
所以,这里我上属性,给大家过过眼.
是可以看到,属性并不是特别多,还是可以理解的. 主要看 elementData这个属性,因为我们的ArrayList就是利用数组来存储数据的.
private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};transient Object[] elementData;private int size;
了解完属性后,接着我们就根据 add 添加元素方法. 这里我就不将代码一行行的贴出来,直接拿主要的部分来进行阅读.
如果走到了grow,就是需要进行扩容了,那么ArrayList是怎么扩容的?每次扩容又是扩容多少呢?如果是第一次并且没有指定集合大小的话,默认值是10.
如果不是第一次,那么minCapacity的指是 size + 1.
先将 elementData的数组长度扩大1.5倍,然后与 minCapacity和MAX_ARRAY_SIZE进行比较,最后得出 newCapacity的值来.
最后调用 Arrays.copyOf来扩容.
最后扩容完了,调用elementData[size++] = e; 将新添加的数据放在最后一位.

再来一个根据下标来添加数据代码.
先是检查下标是否越界,再是调用是否需要扩容的方法.
比如我现在集合有十个元素? 我往第五个插入一个字符串的值是: "PeterWong", 那我是不是将从第五开始后的元素都往后移动一位呢?但是这里并没有发现往后移动赋值的for循环代码呀?那是因为 System.arrraycopy 给我们做了一件这样的事情. 看下图的结果,可以看到System.copyof是将index的值给复制了一份,然后ArrayList再调用 elementData[index] = element给覆盖掉了. 所以我们没有看到for循环去移动值,是因为 System.copyof帮我们做了.
Note: System.copyof在 remove 方法中也是可以看到的.
public void add(int index, E element) {rangeCheckForAdd(index);// Increments modCount!!ensureCapacityInternal(size + 1);System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}

好了,add方法看完了,那么我们来看get方法. 是怎么获取元素的.
根据下标来获取值,再用下标获取值之前,会走一个下标是否越界的方法,如果越界的话,就会抛出异常来.
public E get(int index) {rangeCheck(index);return elementData(index);}// 检查下标是否越界private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}// 获取值E elementData(int index) {return (E) elementData[index];}
好了, add/get都看完了,接着就看 set 方法.
set方法是根据下标来进行赋值的
第一步也是先检查下标是否越界了, 如果没越界就往下
第二步获取之前的值,赋予一个新变量 oldValue
第三步将下标对应的值替换为新值,最后返回旧值.
public E set(int index, E element) {rangeCheck(index);E oldValue = elementData(index);elementData[index] = element;return oldValue;}
最后, 到这里,其实我们使用的 ArrayList 的源码的工作原理,已经很大部分是可以理解的, ArrayList还是很好理解的.
留下的 remove isEmpty indexOf 等方法,大家也可以看看. 其代码理解起来,也不是很有难度.
-- 这里是深文笔记.
-- 交流技术vx : l18776416225
一起学习,一起进步.




