重点
扩容规则:底层是System.arraycopy()这个方法
- 每次扩容都是将新容量设置为1.5 * 旧容量
- 新容量如果小于需要的容量,将新容量设置为需要的容量
- 新容量如果大于可以分配的最大容量(整型最大值 - 8),新容量设置为(需要的容量小于最大分配容量)需要的容量或者设置为(需要的容量大于最大分配容量)整型最大值
懒加载机制:ArrayList初始化的时候并没有直接给数组分配容量,而是使用的一个空数组进行赋值,只有当第一次增加的时候才会真正的给数组进行容量分配。这样是为了防止用户初始化后没有进行使用导致内存的浪费。(只有用户调用无参构造方法的时候才是懒加载,其他两个构造函数是分配的另外一个空数组)
属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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;
|
构造方法
我们可以看到我们经常用的List<Integer> arr = new ArrayList<>()
,并没有一开始给我们初始化为默认的10容量,而是先赋值的是一个空数组。这里其实就是懒加载的开始,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
public ArrayList(int initialCapacity) { ...... if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } ...... }
public ArrayList(Collection<? extends E> c) { ...... if (size == 0) elementData = EMPTY_ELEMENTDATA; } }
|
重要方法
add()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { 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; }
private void ensureExplicitCapacity(int minCapacity) { modCount++;
if (minCapacity - elementData.length > 0) grow(minCapacity); }
private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
|
简易实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
public class ArrList<E>{
private static final int DEFAULT_CAPACITY = 10;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private static final Object[] EMPTY_ELEMENT_DATA = {};
private int size;
private Object[] elementData;
public ArrList() { this.elementData = EMPTY_ELEMENT_DATA; }
public ArrList(int initCapacity) { if (initCapacity < 0){ throw new IllegalArgumentException("Illegal Capacity"); } else if (initCapacity == 0){ this.elementData = EMPTY_ELEMENT_DATA; } else { this.elementData = new Object[initCapacity]; } }
public void add(E e) { lazyLoad(); size++; if (size > elementData.length) { grow(); } elementData[size] = e; }
public void add(int index, E element) { if (index < 0 || index > elementData.length) { throw new IllegalArgumentException("Illegal index"); } lazyLoad(); size++; if (size > elementData.length) { grow(); } System.arraycopy(elementData, index, elementData, index + 1, size - index - 1); elementData[index] = element; }
@SuppressWarnings("unchecked") public E get(int index) { if (index < 0 || index > size){ throw new IllegalArgumentException("Illegal index"); } return (E) elementData[index]; }
public void set(int index, E element) { if (index < 0 || index > size){ throw new IllegalArgumentException("Illegal index"); } elementData[index] = element; }
private void lazyLoad() { if (size == 0){ this.elementData = new Object[DEFAULT_CAPACITY]; } }
private void grow() { int oldSize = elementData.length; int newSize = oldSize + (oldSize >> 1); if (newSize - size < 0) { newSize = size; } if (newSize > MAX_ARRAY_SIZE){ newSize = size > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } elementData = Arrays.copyOf(elementData, newSize); } }
|