ArrayList源码
一、定义
public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess,Cloneable,java.io.Serializable
从中我们可以了解到:
- ArrayList<E>:说明ArrayList支持泛型。
- extends AbstractList<E> :继承了AbstractList。AbstractList提供List接口的骨干实现,以最大限度地减少“随机访问”数据存储(如ArrayList)实现Llist所需的工作。
- implements List<E>:实现了List。实现了所有可选列表操作。
- implements RandomAccess:表明ArrayList支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。
- implements Cloneable:表明其可以调用clone()方法来返回实例的field-for-field拷贝。
- implements java.io.Serializable:表明该类具有序列化功能。
二、构造函数
1 // 默认构造函数 2 ArrayList() 3 4 // capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。 5 ArrayList(int capacity) 6 7 // 创建一个包含collection的ArrayList 8 ArrayList(Collection<? extends E> collection)
三、ArrayList源码解析
1 import java.util.*; 2 3 public class ArrayList<E> extends AbstractList<E> 4 implements List<E>, RandomAccess, Cloneable, java.io.Serializable 5 { 6 // 序列版本号 7 private static final long serialVersionUID = 8683452581122892189L; 8 9 // 保存ArrayList中数据的数组 10 private transient Object[] elementData; 11 12 // ArrayList中实际数据的数量 13 private int size; 14 15 // ArrayList带容量大小的构造函数。 16 public ArrayList(int initialCapacity) { 17 super(); 18 if (initialCapacity < 0) 19 throw new IllegalArgumentException("Illegal Capacity: "+ 20 initialCapacity); 21 // 新建一个数组 22 this.elementData = new Object[initialCapacity]; 23 } 24 25 // ArrayList构造函数。默认容量是10。 26 public ArrayList() { 27 this(10); 28 } 29 30 // 创建一个包含collection的ArrayList 31 public ArrayList(Collection<? extends E> c) { 32 elementData = c.toArray(); 33 size = elementData.length; 34 // c.toArray might (incorrectly) not return Object[] (see 6260652) 35 if (elementData.getClass() != Object[].class) 36 elementData = Arrays.copyOf(elementData, size, Object[].class); 37 } 38 39 // 添加元素e 40 public boolean add(E e) { 41 // 确定ArrayList的容量大小 42 ensureCapacity(size + 1); // Increments modCount!! 43 // 添加e到ArrayList中 44 elementData[size++] = e; 45 return true; 46 } 47 48 // 确定ArrarList的容量。 49 // 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1” 50 public void ensureCapacity(int minCapacity) { 51 // 将“修改统计数”+1 52 modCount++; 53 int oldCapacity = elementData.length; 54 // 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1” 55 if (minCapacity > oldCapacity) { 56 Object oldData[] = elementData; 57 int newCapacity = (oldCapacity * 3)/2 + 1; 58 if (newCapacity < minCapacity) 59 newCapacity = minCapacity; 60 elementData = Arrays.copyOf(elementData, newCapacity); 61 } 62 } 63 64 // 返回ArrayList的实际大小 65 public int size() { 66 return size; 67 } 68 69 // 返回ArrayList是否包含Object(o) 70 public boolean contains(Object o) { 71 return indexOf(o) >= 0; 72 } 73 74 // 正向查找,返回元素的索引值 75 public int indexOf(Object o) { 76 if (o == null) { 77 for (int i = 0; i < size; i++) 78 if (elementData[i]==null) 79 return i; 80 } else { 81 for (int i = 0; i < size; i++) 82 if (o.equals(elementData[i])) 83 return i; 84 } 85 return -1; 86 } 87 88 // 返回ArrayList是否为空 89 public boolean isEmpty() { 90 return size == 0; 91 } 92 93 94 // 返回ArrayList的Object数组 95 public Object[] toArray() { 96 return Arrays.copyOf(elementData, size); 97 } 98 99 // 返回ArrayList的模板数组。所谓模板数组,即可以将T设为任意的数据类型 100 public <T> T[] toArray(T[] a) { 101 // 若数组a的大小 < ArrayList的元素个数; 102 // 则新建一个T[]数组,数组大小是“ArrayList的元素个数”,并将“ArrayList”全部拷贝到新数组中 103 if (a.length < size) 104 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 105 106 // 若数组a的大小 >= ArrayList的元素个数; 107 // 则将ArrayList的全部元素都拷贝到数组a中。 108 System.arraycopy(elementData, 0, a, 0, size); 109 if (a.length > size) 110 a[size] = null; 111 return a; 112 } 113 114 // 获取index位置的元素值 115 public E get(int index) { 116 //判断数组是否越界 117 RangeCheck(index); 118 119 return (E) elementData[index]; 120 } 121 122 // 将e添加到ArrayList的指定位置 123 public void add(int index, E element) { 124 if (index > size || index < 0) 125 throw new IndexOutOfBoundsException( 126 "Index: "+index+", Size: "+size); 127 128 ensureCapacity(size+1); // Increments modCount!! 129 System.arraycopy(elementData, index, elementData, index + 1, 130 size - index); 131 elementData[index] = element; 132 size++; 133 } 134 135 // 删除ArrayList指定位置的元素 136 public E remove(int index) { 137 RangeCheck(index); 138 139 modCount++; 140 E oldValue = (E) elementData[index]; 141 142 int numMoved = size - index - 1; 143 if (numMoved > 0) 144 System.arraycopy(elementData, index+1, elementData, index, 145 numMoved); 146 elementData[--size] = null; // Let gc do its work 147 148 return oldValue; 149 } 150 151 // 删除ArrayList的指定元素 152 public boolean remove(Object o) { 153 if (o == null) { 154 for (int index = 0; index < size; index++) 155 if (elementData[index] == null) { 156 fastRemove(index); 157 return true; 158 } 159 } else { 160 for (int index = 0; index < size; index++) 161 if (o.equals(elementData[index])) { 162 fastRemove(index); 163 return true; 164 } 165 } 166 return false; 167 } 168 169 // 清空ArrayList,将全部的元素设为null 170 public void clear() { 171 modCount++; 172 173 for (int i = 0; i < size; i++) 174 elementData[i] = null; 175 176 size = 0; 177 } 178 179 // 将ArrayList的“容量,所有的元素值”都写入到输出流中 180 private void writeObject(java.io.ObjectOutputStream s) 181 throws java.io.IOException{ 182 // Write out element count, and any hidden stuff 183 int expectedModCount = modCount; 184 s.defaultWriteObject(); 185 186 // 写入“数组的容量” 187 s.writeInt(elementData.length); 188 189 // 写入“数组的每一个元素” 190 for (int i=0; i<size; i++) 191 s.writeObject(elementData[i]); 192 193 if (modCount != expectedModCount) { 194 throw new ConcurrentModificationException(); 195 } 196 } 197 198 // java.io.Serializable的读取函数:根据写入方式读出 199 // 先将ArrayList的“容量”读出,然后将“所有的元素值”读出 200 private void readObject(java.io.ObjectInputStream s) 201 throws java.io.IOException, ClassNotFoundException { 202 // Read in size, and any hidden stuff 203 s.defaultReadObject(); 204 205 // 从输入流中读取ArrayList的“容量” 206 int arrayLength = s.readInt(); 207 Object[] a = elementData = new Object[arrayLength]; 208 209 // 从输入流中将“所有的元素值”读出 210 for (int i=0; i<size; i++) 211 a[i] = s.readObject(); 212 } 213 }
总结:
(01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。
(02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
(03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
(04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
参考博客:Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
水滴石穿,成功的速度一定要超过父母老去的速度! 少尉【3】