閒來無事,有空會繼續寫下 List LinkedList CopyOnWriteArrayList Set HashSet LinkedHashSet Map HashMap IdentityHashMap LinkedHashMap TreeMap ConcurrentHashMap Queue ArrayBlockingQueue LinkedBlockingQueue ConcurrentLinkedQueue 爲節省空間對於非重點代碼不作展現
ArrayList底層是由數組組成的一種數據結構,能夠進行動態的增刪改查html
ArrayList通常用於對數據的存儲java
帶上問題去找答案數組
從咱們使用ArrayList開始 new ArrayList<>(); public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } private static final Object[] EMPTY_ELEMENTDATA = {}; private transient Object[] elementData; elementData爲儲存數據所用容器,經過默認構造方法建立的ArrayList容器爲空
public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e;//size表示當前使用下表,直接將元素放入到elementData的指定位置 return true; } 指定位置的添加,設計到元素的後移 public void add(int index, E element) { rangeCheckForAdd(index);//檢查是否超出 ensureCapacityInternal(size + 1); // Increments modCount!! 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));//很常見的異常 }
public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this.modCount = parent.modCount; this.size--; return result; } final void checkForComodification() { if (modCount != expectedModCount)//針對在對於list進行遍歷時進行其餘操做,modCount會改變,而expectedModCount值在listInterator時給定的會拋出異常 throw new ConcurrentModificationException(); }
public E get(int index) { rangeCheck(index);//這就沒啥好多的了 return elementData(index); }
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { //若是容器爲空,初始化容器,兩個值中取最大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;//操做次數+1 // overflow-conscious code if (minCapacity - elementData.length > 0) //擴容,當前元素數量已經等於容器了須要進行擴容 grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length;//當前容器大小 int newCapacity = oldCapacity + (oldCapacity >> 1);// oldCapacity + oldCapacity*0.5 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);//計算是否超出 // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);//擴容 } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow //若是爲負數拋出內存溢出錯誤 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? //尚未爲負數,那麼元素最大大小改成int的最大值,注意MAX_ARRAY_SIZE爲最大值-8 Integer.MAX_VALUE : MAX_ARRAY_SIZE; } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
ArrayList不是線程安全的安全
以添加爲例 elementData[size++] = e; 一個 ArrayList ,在添加一個元素的時候,它可能會有兩步來完成: 1. 在 Items[Size] 的位置存放此元素; 2. 增大 Size 的值。 在單線程運行的狀況下,若是 Size = 0,添加一個元素後,此元素在位置 0,並且 Size=1; 而若是是在多線程狀況下,好比有兩個線程,線程 A 先將元素存放在位置 0。可是此時 CPU 調度線程A暫停,線程 B 獲得運行的機會。線程B也向此 ArrayList 添加元素,由於此時 Size 仍然等於 0 (注意哦,咱們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),因此線程B也將元素存放在位置0。而後線程A和線程B都繼續運行,都增長 Size 的值。 那好,如今咱們來看看 ArrayList 的狀況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是「線程不安全」了。