对于平常开发的时候遇到的ArrayList,在此做一个简单的源码阅读记录,JDK1.8版本。 首先看下ArrayList的类关系图,可以看到实现了 Serializable接口,支持序列化与反序列化; Cloneable接口,可以被克隆; RandomAccess接口,支持随机访问,另外fori循环会比迭代器循环效率高,代码如下: 比这个循环运行得更快:Java源码篇之容器类——ArrayList
1、前言
2、ArrayList的类关系
for (int i=0, n=list.size(); i < n; i++) list.get(i);
for (Iterator i=list.iterator(); i.hasNext(); ) i.next();
3、ArrayList的源码
一、类的属性
/** * 默认初始容量 */ private static final int DEFAULT_CAPACITY = 10; /** * (用于空实例的)共享空数组实例 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * (用于默认大小的空实例的)共享空数组实例,我们将其与空的元素数据区分开来, * 以了解何时添加第一个元素. */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * 存储ArrayList元素的数组缓冲区。ArrayList的容量是此数组缓冲区的长度。任何 * elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA elementData * 将在添加第一个元素时扩展到默认容量(10)。 */ transient Object[] elementData; // transient关键字标记的成员变量不参与序列化过程 /** * ArrayList的大小(包含的元素数) */ private int size; /** * 可分配的数组的最大大小,可能会导致OutOfMemory错误:Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
二、add()方法
// 默认往数组末尾添加元素 public boolean add(E e) { ensureCapacityInternal(size + 1); // 大小加1 elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { // minCapacity = size + 1 // elementData 是成员变量 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) {/ 如果 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 数组为空时,返回较大的数 return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; // 数组非空时,返回 minCapacity = size + 1 } private void ensureExplicitCapacity(int minCapacity) { // minCapacity = size + 1 modCount++; // 计数 // 数组元素个数加1之后如果大于当前数组长度,则进行扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // minCapacity = size + 1 int oldCapacity = elementData.length; // 旧数组的长度 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新数组的长度 = 1.5倍旧数组长度 // 新数组长度小于数组元素个数加1 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 新数组长度大于数组最大值 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 创建一个新的数组,并把旧数组元素复制过去,newCapacity为新数组大小 elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // 新数组长度大于数组最大值,并且minCapacity<0才会抛出oom错误 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } // 指定位置添加元素 public void add(int index, E element) { // 下标合法性校验 rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // 生成一个index位置为null的新数组 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
三、get()方法
public E get(int index) { // 检查合法性 rangeCheck(index); // 返回数组元素 return elementData(index); } private void rangeCheck(int index) { // 下标位置大于等于数组长度的时候(数组下标从0开始),抛出下标越界异常 if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } E elementData(int index) { return (E) elementData[index]; }
四、remove()方法
// 删除指定下标的元素 public E remove(int index) { // 校验合法性 rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) // 生成一个新数组 System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; } // 删除指定的元素,第一个出现的 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }
五、set()方法
// 将index位置的元素置换成element public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }
4、总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算