1 package com.wjq.javautils; 2 3 import java.util.AbstractList; 4 import java.util.ArrayList; 5 import java.util.Arrays; 6 import java.util.Collection; 7 import java.util.Comparator; 8 import java.util.ConcurrentModificationException; 9 import java.util.List; 10 import java.util.RandomAccess; 11 12 /** 13 * 14 * @author WangJingQian 15 * 16 * @param <E> 17 */ 18 public class MyArrayList<E> extends AbstractList<E> 19 implements List<E>, RandomAccess, Cloneable, java.io.Serializable { 20 21 /** 22 * 序列化版本唯一标识符,版本向下兼容。 23 */ 24 private static final long serialVersionUID = -6534304769377827244L; 25 26 // 默认初始容量 27 private static final int DEFAULT_CAPACITY = 10; 28 29 // 容量为0的空数组 30 private static final Object[] EMPTY_ELEMENTDATA = {}; 31 32 // 默认容量的空数组,向空数组中插入第1个元素时该数组可用于判断初始的容量是 33 // 多少(0或10)从而确定扩容的大小。 34 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 35 36 // 瞬态的缓冲数组 使用transient关键字目的是只序列化实际存储的那些元素,而不是整个数组。 37 private transient Object[] elementData; 38 39 // 数组实际存储的元素数量 40 private int size; 41 42 // 带初始容量的构造方法 43 public MyArrayList(int initialCapacity) { 44 if (initialCapacity > 0) { 45 this.elementData = new Object[initialCapacity]; 46 } else if (initialCapacity == 0) { 47 // 指向空数组 48 this.elementData = EMPTY_ELEMENTDATA; 49 } else { 50 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); 51 } 52 } 53 54 // 无参构造方法 55 public MyArrayList() { 56 // 指向默认容量为10的空数组 57 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 58 } 59 60 // Collection对象作为参数的构造方法 61 public MyArrayList(Collection<? extends E> c) { 62 elementData = c.toArray(); 63 if ((size = elementData.length) != 0) { 64 // c.toArray might (incorrectly) not return Object[] (see 6260652) 65 // 返回的数组类型可能不是Object[],要看运行时类型(实际类型),例如String[]。这样会导致向下转型,例如修改元素时指向了非继承或实现关系的对象时会出错,String->Integer。 66 // 原因在于里面存储的元素可能不是Object类型。 67 if (elementData.getClass() != Object[].class) { 68 // 重新指向Object数组。 69 // Arrays.copyOf会创建新数组,返回引用。 70 elementData = Arrays.copyOf(elementData, size, Object[].class); 71 } 72 } else { 73 // replace with empty array. 74 this.elementData = EMPTY_ELEMENTDATA; 75 } 76 } 77 78 // 将数组长度削减到元素数量对应的长度。 79 public void trimToSize() { 80 int count = size; 81 // 如果实际元素数量小于数组长度 82 if (count < elementData.length) { 83 elementData = (count == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, count); 84 } 85 } 86 87 // 公有方法,保证容量。 88 public void ensureCapacity(int minCapacity) { 89 // 最小增量 90 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 91 // any size if not default element table 92 ? 0 93 // larger than default for default empty table. It‘s already 94 // supposed to be at default size. 95 : DEFAULT_CAPACITY; 96 97 // 如果最小容量大于最小增量则确保最小容量足够。 98 if (minCapacity > minExpand) { 99 ensureExplicitCapacity(minCapacity); 100 } 101 } 102 103 // 确保内部的容量足够。 104 private void ensureCapacityInternal(int minCapacity) { 105 // 如果elementData指向的是默认容量的空数组则说明当前容量为10。 106 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 107 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 108 } 109 110 // 确保最小容量足够。 111 ensureExplicitCapacity(minCapacity); 112 } 113 114 // 确保最小容量足够。 115 private void ensureExplicitCapacity(int minCapacity) { 116 // overflow-conscious code 117 // 如果最小容量大于数组长度则扩容。 118 if (minCapacity - elementData.length > 0) { 119 grow(minCapacity); 120 } 121 } 122 123 // 可分配的数组最大容量 124 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 125 126 // 扩容 127 private void grow(int minCapacity) { // minCapacity是需要达到的最小容量。 128 // overflow-conscious code 129 // 原来的容量是数组长度。 130 int oldCapacity = elementData.length; 131 // 新的容量是1.5倍的原有容量。 132 int newCapacity = oldCapacity + (oldCapacity >> 1); 133 134 // 如果最小容量大于1.5倍的原有容量则最小容量设为新的容量。 135 if (newCapacity - minCapacity < 0) { 136 newCapacity = minCapacity; 137 } 138 // 如果新的容量大于可分配的数组最大容量 139 if (newCapacity - MAX_ARRAY_SIZE > 0) { 140 // minCapacity is usually close to size, so this is a win: 141 newCapacity = hugeCapacity(minCapacity); 142 } 143 144 // elementData指向扩容后的新数组。 145 elementData = Arrays.copyOf(elementData, newCapacity); 146 } 147 148 // 确保数组容量最大为Integer.MAX_VALUE。 149 private static int hugeCapacity(int minCapacity) { 150 // 如果最小容量溢出则抛出内存不足错误。 151 // overflow 152 if (minCapacity < 0) { 153 throw new OutOfMemoryError(); 154 } 155 156 // 如果最小容量超过了可分配的数组最大容量则返回整形的最大值作为新容量,否则返回可分配的数组最大容量作为新容量。 157 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 158 } 159 160 // 获取实际元素数量。 161 @Override 162 public int size() { 163 return size; 164 } 165 166 // 判断数组是否为空即判断是否存在实际元素。 167 @Override 168 public boolean isEmpty() { 169 return size == 0; 170 } 171 172 // 判断是否包含某个元素,通过该元素对应的下标来判断。 173 @Override 174 public boolean contains(Object o) { 175 return indexOf(o) >= 0; 176 } 177 178 // 顺序获取某个元素对应的下标。 179 @Override 180 public int indexOf(Object o) { 181 if (o == null) { // 如果该元素为空 182 for (int i = 0; i < size; i++) { 183 if (elementData[i] == null) { 184 return i; 185 } 186 } 187 } else { // 否则 188 for (int i = 0; i < size; i++) { 189 if (o.equals(elementData[i])) { 190 return i; 191 } 192 } 193 } 194 195 // 没有找到该元素。 196 return -1; 197 } 198 199 // 逆序获取某个元素对应的下标。 200 @Override 201 public int lastIndexOf(Object o) { 202 // 如果该元素为空 203 if (o == null) { 204 for (int i = size - 1; i >= 0; i--) { 205 if (elementData[i] == null) { 206 return i; 207 } 208 } 209 } else { 210 for (int i = size - 1; i >= 0; i--) { 211 if (o.equals(elementData[i])) { 212 return i; 213 } 214 } 215 } 216 217 // 没有找到该元素。 218 return -1; 219 } 220 221 // 浅复制,没有复制数组中元素作为引用指向的对象。 222 // 该方法返回的是当前ArrayList对象的浅复制对象引用。 223 @Override 224 public Object clone() { 225 try { 226 // 调用父类复制方法。 227 // 使用E会出现警告 228 @SuppressWarnings("unchecked") 229 MyArrayList<E> v = (MyArrayList<E>) super.clone(); 230 // v.elementData指向存储原来对象(元素)的新数组。 231 v.elementData = Arrays.copyOf(elementData, size); 232 233 return v; 234 } catch (CloneNotSupportedException e) { 235 // this shouldn‘t happen, since we are Cloneable 236 throw new InternalError(e); 237 } 238 } 239 240 // 返回一个数据拷贝后的Object数组。 241 @Override 242 public Object[] toArray() { 243 return Arrays.copyOf(elementData, size); 244 } 245 246 // 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 247 // 返回数组的运行时类型是指定数组的运行时类型。 248 @Override 249 @SuppressWarnings("unchecked") 250 public <T> T[] toArray(T[] a) { 251 if (a.length < size) { 252 // Make a new array of a‘s runtime type, but my contents: 253 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 254 } 255 256 System.arraycopy(elementData, 0, a, 0, size); 257 258 if (a.length > size) { 259 a[size] = null; 260 } 261 262 return a; 263 } 264 265 // Positional Access Operations 266 // 按下标随机访问元素。 267 @SuppressWarnings("unchecked") 268 E elementData(int index) { 269 return (E) elementData[index]; 270 } 271 272 // 通过参数检查之后按下标随机访问元素。 273 @Override 274 public E get(int index) { 275 rangeCheck(index); 276 277 return elementData(index); 278 } 279 280 // 通过参数检查之后按下标修改元素内容并返回原来的元素内容。 281 @Override 282 public E set(int index, E element) { 283 rangeCheck(index); 284 285 E oldValue = elementData(index); 286 elementData[index] = element; 287 288 return oldValue; 289 } 290 291 // 末尾增加元素。 292 @Override 293 public boolean add(E e) { 294 // 确保容量足够。 295 ensureCapacityInternal(size + 1); 296 elementData[size++] = e; 297 298 return true; 299 } 300 301 // 按下标增加元素。可能需要向后移动。 302 @Override 303 public void add(int index, E element) { 304 // 下标检查。 305 rangeCheckForAdd(index); 306 307 // 确保容量足够。 308 ensureCapacityInternal(size + 1); 309 // 下标大于index的部分向后移。注意size>=index。 310 System.arraycopy(elementData, index, elementData, index + 1, size - index); 311 elementData[index] = element; // 插入新元素。 312 size++; // 实际元素数量增加。 313 } 314 315 // 按下标删除元素并返回原来的元素内容。 316 @Override 317 public E remove(int index) { 318 // 下标检查。 319 rangeCheck(index); 320 321 E oldValue = elementData(index); 322 323 // 可能需要向前移动。注意size>=index。所以numMoved可能小于0。 324 int numMoved = size - index - 1; 325 if (numMoved > 0) { 326 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 327 } 328 elementData[--size] = null; // clear to let GC do its work 329 330 return oldValue; 331 } 332 333 // 移除此列表中首次出现的指定元素(如果存在)。 334 @Override 335 public boolean remove(Object o) { 336 if (o == null) { // 如果是空元素 337 for (int index = 0; index < size; index++) { 338 if (elementData[index] == null) { 339 fastRemove(index); // 不返回旧值。 340 return true; 341 } 342 } 343 } else { // 否则 344 for (int index = 0; index < size; index++) { 345 if (o.equals(elementData[index])) { 346 fastRemove(index); // 不返回旧值。 347 return true; 348 } 349 } 350 } 351 352 // 没有找到该元素。 353 return false; 354 } 355 356 // 根据下标删除元素,但不返回旧值。 357 private void fastRemove(int index) { 358 // 可能需要向前移动。注意size>=index。所以numMoved可能小于0。 359 int numMoved = size - index - 1; 360 if (numMoved > 0) { 361 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 362 } 363 elementData[--size] = null; // clear to let GC do its work 364 } 365 366 // 移除此列表中的所有元素。 367 @Override 368 public void clear() { 369 // clear to let GC do its work 370 for (int i = 0; i < size; i++) { 371 elementData[i] = null; 372 } 373 374 size = 0; 375 } 376 377 // 移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。 378 @Override 379 protected void removeRange(int fromIndex, int toIndex) { 380 // 可能需要向前移动。 381 int numMoved = size - toIndex; // 元素移动数量 382 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); 383 384 // clear to let GC do its work 385 // newSize是新的实际元素数量。 386 int newSize = size - (toIndex - fromIndex); 387 for (int i = newSize; i < size; i++) { 388 elementData[i] = null; 389 } 390 size = newSize; // 更新实际元素数量。 391 } 392 393 // 下标上界范围检查。 394 private void rangeCheck(int index) { 395 if (index >= size) { 396 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 397 } 398 } 399 400 // 增加元素时下标范围检查。 401 private void rangeCheckForAdd(int index) { 402 if (index > size || index < 0) { 403 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 404 } 405 } 406 407 // 输出越界异常提示。 408 private String outOfBoundsMsg(int index) { 409 return "Index: " + index + ", Size: " + size; 410 } 411 412 // 序列化,elementData写入输出流。 413 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { 414 // Write out element count, and any hidden stuff 415 // 版本向下兼容,旧版本的反序列化值在新版本中序列化会增加新属性的默认值。 416 s.defaultWriteObject(); 417 418 // Write out size as capacity for behavioural compatibility with clone() 419 // 版本向下兼容,旧版本需要读取数组长度length。如果不写入size,会导致旧版本反序列化时出现异常。 420 s.writeInt(size); 421 422 // Write out all elements in the proper order. 423 for (int i = 0; i < size; i++) { 424 s.writeObject(elementData[i]); 425 } 426 } 427 428 // 反序列化,elementData从输入流中读取。 429 private void readObject(java.io.ObjectInputStream s) 430 throws java.io.IOException, ClassNotFoundException { 431 // elementData指向空数组。 432 elementData = EMPTY_ELEMENTDATA; 433 434 // Read in size, and any hidden stuff 435 // 版本向下兼容,旧版本的序列化值在新版本中反序列化时会自动忽略新属性。 436 s.defaultReadObject(); 437 438 // Read in capacity 439 s.readInt(); // ignored 440 441 // size是通过ObjectOutputStream类中defaultWriteFields方法和ObjectInputStream类中defaultReadFields方法得到的。 442 // 如果存在元素 443 if (size > 0) { 444 // be like clone(), allocate array based upon size not capacity 445 // 确保容量足够。 446 ensureCapacityInternal(size); 447 448 Object[] a = elementData; 449 // Read in all elements in the proper order. 450 for (int i = 0; i < size; i++) { 451 a[i] = s.readObject(); 452 } 453 } 454 } 455 456 // 排序 457 @Override 458 @SuppressWarnings("unchecked") 459 public void sort(Comparator<? super E> c) { 460 Arrays.sort((E[]) elementData, 0, size, c); 461 } 462 }