ArrayList, LinkedList, Vector - dudu:史上最詳解
我們來比較一下ArrayList, LinkedLIst和Vector它們之間的區別。BZ的JDK版本是1.7.0_80
經常在面試的時候,或者在大家做project的時候,都會被它們的區別產生疑惑。或者對它們的用法並不是很了解。那么我們今天就來看看他們的區別和用法。
以下是本文的大綱:
一.ArrayList,LinkedList和Vector的區別
若有不正之處,還請多多諒解,並希望批評指正。
請尊重作者勞動成果,轉發請標明blog地址
https://www.cnblogs.com/hongten/p/hongten_arraylist_linkedlist_vector.html
一.ArrayList,LinkedList和Vector的區別
ArrayList, LinkedList和Vector都實現了List接口,所使用的方法也很相似,主要區別在於實現方法的不同,所有對不同的操作具有不同的效率。
1.ArrayList
ArrayList是一個可以改變大小的,線程不同步(不支持並發)的數組,內部值可以為null。 當更多的元素加入到ArrayList中時,其大小會自動增加,內部元素可以直接通過get/set方法進行訪問,因為ArrayList本質上即使一個數組。
因為ArrayList是不支持並發的數組,但是如果我們在使用的過程中需要ArrayList也有同步功能,可以使用Collections.synchronziedList(new ArrayList<E e>())方法實現(在后面我們會講到)。
2.Vector
之所以把Vector放在這里的原因是因為Vector和ArrayList是否類似,但是它是屬於線程同步(支持並發)的數組,並且內部值也可以為null。如果你的程序本身是線程安全的(沒有多個線程之間共享同一個集合/對象),那么請使用ArrayList吧。
3.LinkedList
LinkedList底層是基於雙鏈表實現的,在添加和刪除元素時具有比ArrayList更好的性能。但是在get/set方面要弱於ArrayList(前提是這些對比是在數據量很大或者操作很繁瑣的情況下)。LinkedList內部值可以為null,但是當我們調用值為null的元素的時候會出現NullPointerException。
LinkedList更適合於以下場景:
I.沒有大量的隨機訪問操作。
II.有大量的add/remove操作。
概括起來大概是這個樣子:
ArrayList和Vector它們底層實現為數組,值可為null, ArrayList不支持並發,Vector支持並發;
LinkedList底層基於雙鏈表,因此在add/remove元素時比ArrayList要快(注意前提)。
二.詳解ArrayList
先來看看ArrayList的源碼
1 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { 2 private static final long serialVersionUID = 8683452581122892189L; 3 4 //默認數組大小為10 5 private static final int DEFAULT_CAPACITY = 10; 6 //空數組對象 7 private static final Object[] EMPTY_ELEMENTDATA = {}; 8 //ArrayList底層基於該數組實現 9 private transient Object[] elementData; 10 //ArrayList中實際數據的大小 11 private int size; 12 13 //帶有初始化容量大小的構造函數 14 public ArrayList(int initialCapacity) { 15 super(); 16 if (initialCapacity < 0) 17 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); 18 //使數組初始化為指定容量大小 19 this.elementData = new Object[initialCapacity]; 20 } 21 22 //無參構造函數 23 public ArrayList() { 24 super(); 25 //這里是把數組設置為空數組對象 26 this.elementData = EMPTY_ELEMENTDATA; 27 } 28 29 //創建一個包含Collection的ArrayList 30 public ArrayList(Collection<? extends E> c) { 31 elementData = c.toArray(); 32 size = elementData.length; 33 if (elementData.getClass() != Object[].class) 34 elementData = Arrays.copyOf(elementData, size, Object[].class); 35 } 36 37 //將當期容量值設置為實際元素個數 38 public void trimToSize() { 39 modCount++; 40 if (size < elementData.length) { 41 elementData = Arrays.copyOf(elementData, size); 42 } 43 } 44 45 //確保ArrayList容量,如果 46 public void ensureCapacity(int minCapacity) { 47 int minExpand = (elementData != EMPTY_ELEMENTDATA) 48 // any size if real element table 49 ? 0 50 // larger than default for empty table. It's already supposed to be 51 // at default size. 52 : DEFAULT_CAPACITY; 53 54 if (minCapacity > minExpand) { 55 ensureExplicitCapacity(minCapacity); 56 } 57 } 58 59 private void ensureCapacityInternal(int minCapacity) { 60 //初始化時候,elementData是為空數組對象EMPTY_ELEMENTDATA,所以會去設置minCapacity的值 61 if (elementData == EMPTY_ELEMENTDATA) { 62 //設置minCapacity值,比較minCapacity和默認容量(DEFAULT_CAPACITY=10) 63 //把最大值賦值給minCapacity 64 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 65 } 66 //確定明確的容量大小 67 ensureExplicitCapacity(minCapacity); 68 } 69 70 //確定明確的容量大小 71 private void ensureExplicitCapacity(int minCapacity) { 72 modCount++; 73 74 // overflow-conscious code 75 if (minCapacity - elementData.length > 0) 76 grow(minCapacity); 77 } 78 79 //最大數組大小=Integer.MAX_VALUE - 8 80 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 81 82 //擴容方法 83 private void grow(int minCapacity) { 84 // overflow-conscious code 85 int oldCapacity = elementData.length; 86 int newCapacity = oldCapacity + (oldCapacity >> 1); 87 if (newCapacity - minCapacity < 0) 88 newCapacity = minCapacity; 89 if (newCapacity - MAX_ARRAY_SIZE > 0) 90 newCapacity = hugeCapacity(minCapacity); 91 // minCapacity is usually close to size, so this is a win: 92 elementData = Arrays.copyOf(elementData, newCapacity); 93 } 94 95 private static int hugeCapacity(int minCapacity) { 96 if (minCapacity < 0) // overflow 97 throw new OutOfMemoryError(); 98 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 99 } 100 101 //獲取大小 102 public int size() { 103 return size; 104 } 105 106 //判斷是否為空 107 public boolean isEmpty() { 108 return size == 0; 109 } 110 111 //是否包含某個元素/對象 112 public boolean contains(Object o) { 113 return indexOf(o) >= 0; 114 } 115 116 //正向查詢,如果找到,則返回對象的索引值 117 public int indexOf(Object o) { 118 if (o == null) { 119 for (int i = 0; i < size; i++) 120 if (elementData[i] == null) 121 return i; 122 } else { 123 for (int i = 0; i < size; i++) 124 if (o.equals(elementData[i])) 125 return i; 126 } 127 return -1; 128 } 129 130 //反向查找,如果找到,則返回對象的索引值 131 public int lastIndexOf(Object o) { 132 if (o == null) { 133 for (int i = size - 1; i >= 0; i--) 134 if (elementData[i] == null) 135 return i; 136 } else { 137 for (int i = size - 1; i >= 0; i--) 138 if (o.equals(elementData[i])) 139 return i; 140 } 141 return -1; 142 } 143 144 //clone 145 public Object clone() { 146 try { 147 @SuppressWarnings("unchecked") 148 ArrayList<E> v = (ArrayList<E>) super.clone(); 149 v.elementData = Arrays.copyOf(elementData, size); 150 v.modCount = 0; 151 return v; 152 } catch (CloneNotSupportedException e) { 153 // this shouldn't happen, since we are Cloneable 154 throw new InternalError(); 155 } 156 } 157 158 @SuppressWarnings("unchecked") 159 E elementData(int index) { 160 return (E) elementData[index]; 161 } 162 163 //根據索引值查詢對象 164 public E get(int index) { 165 rangeCheck(index); 166 167 return elementData(index); 168 } 169 170 //根據索引值,把element設置為該索引所對應的值 171 public E set(int index, E element) { 172 rangeCheck(index); 173 174 E oldValue = elementData(index); 175 elementData[index] = element; 176 return oldValue; 177 } 178 179 //向ArrayList中添加一個元素 180 public boolean add(E e) { 181 ensureCapacityInternal(size + 1); // Increments modCount!! 182 elementData[size++] = e; 183 return true; 184 } 185 186 //根據指定的索引值添加對象 187 public void add(int index, E element) { 188 rangeCheckForAdd(index); 189 190 ensureCapacityInternal(size + 1); // Increments modCount!! 191 System.arraycopy(elementData, index, elementData, index + 1, size - index); 192 elementData[index] = element; 193 size++; 194 } 195 196 //刪除指定索引值所在的對象,並返回所刪除的對象 197 public E remove(int index) { 198 rangeCheck(index); 199 200 modCount++; 201 E oldValue = elementData(index); 202 203 int numMoved = size - index - 1; 204 if (numMoved > 0) 205 //所有對象向前移動 206 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 207 //把數組最后一個元素置空,以便java虛擬機回收 208 elementData[--size] = null; // clear to let GC do its work 209 210 return oldValue; 211 } 212 213 //刪除對象,並返回是否刪除成功 214 public boolean remove(Object o) { 215 if (o == null) { 216 for (int index = 0; index < size; index++) 217 if (elementData[index] == null) { 218 fastRemove(index); 219 return true; 220 } 221 } else { 222 for (int index = 0; index < size; index++) 223 if (o.equals(elementData[index])) { 224 fastRemove(index); 225 return true; 226 } 227 } 228 return false; 229 } 230 231 //直接刪除掉索引指向的元素 232 private void fastRemove(int index) { 233 modCount++; 234 int numMoved = size - index - 1; 235 if (numMoved > 0) 236 //所有對象向前移動 237 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 238 //把數組最后一個元素置空,以便java虛擬機回收 239 elementData[--size] = null; // clear to let GC do its work 240 } 241 242 //把數組置空 243 public void clear() { 244 modCount++; 245 246 // clear to let GC do its work 247 for (int i = 0; i < size; i++) 248 elementData[i] = null; 249 250 size = 0; 251 } 252 253 //添加包含Collection的元素對象 254 public boolean addAll(Collection<? extends E> c) { 255 Object[] a = c.toArray(); 256 int numNew = a.length; 257 ensureCapacityInternal(size + numNew); // Increments modCount 258 System.arraycopy(a, 0, elementData, size, numNew); 259 size += numNew; 260 return numNew != 0; 261 } 262 263 //在所給定的索引上,添加包含Collection的元素對象 264 public boolean addAll(int index, Collection<? extends E> c) { 265 rangeCheckForAdd(index); 266 267 Object[] a = c.toArray(); 268 int numNew = a.length; 269 ensureCapacityInternal(size + numNew); // Increments modCount 270 271 int numMoved = size - index; 272 if (numMoved > 0) 273 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); 274 275 System.arraycopy(a, 0, elementData, index, numNew); 276 size += numNew; 277 return numNew != 0; 278 } 279 280 //刪除某一個區域對象 281 protected void removeRange(int fromIndex, int toIndex) { 282 modCount++; 283 int numMoved = size - toIndex; 284 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); 285 286 // clear to let GC do its work 287 int newSize = size - (toIndex - fromIndex); 288 for (int i = newSize; i < size; i++) { 289 elementData[i] = null; 290 } 291 size = newSize; 292 } 293 294 //如果索引值超過了數組大小,拋出IndexOutOfBoundsException異常 295 private void rangeCheck(int index) { 296 if (index >= size) 297 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 298 } 299 300 //添加元素時,檢查索引大小,如果索引值大於容量(size)大小或小於0,則拋出IndexOutOfBoundsException異常 301 private void rangeCheckForAdd(int index) { 302 if (index > size || index < 0) 303 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 304 } 305 306 //用於迭代ArrayList 307 public ListIterator<E> listIterator() { 308 return new ListItr(0); 309 } 310 }
我們可以看到ArrayList繼承了AbstractList,並且實現了List, RandomAccess, Cloneable, Serializable接口,ArrayList是一個可變大小的數組。它提供了很多方法:size, isEmpty, get, set, listIterator,add,addAll等等。
我們來分析一下下面的代碼:
1 List<String> arrList = new ArrayList<String>(); 2 System.out.println(arrList.size());//輸出:0 3 arrList.add("hongten"); 4 System.out.println(arrList.size());//輸出:1
當我們創建一個ArrayList的時候,其數組大小(size)是為0,即一個空數組。當我們往數組里面添加一個元素‘hongten’后,其數組大小變為1.
這和我們之前的JDK1.5有一點區別(默認情況下,數組大小為10)。
我們new ArrayList()的時候,調用的是ArrayList的無參構造函數:
ArrayList無參構造函數
JDK1.7里面ArrayList無參構造函數,默認情況下,數組為一個空數組。
1 //無參構造函數 2 public ArrayList() { 3 super();//因為繼承了AbstractList,所以調用AbstractList的構造函數 4 //這里是把數組設置為空數組對象 5 this.elementData = EMPTY_ELEMENTDATA; 6 }
JDK1.5里面ArrayList無參構造函數,默認情況下,數組大小為10.(由於本文針對JDK1.7.0_80,所以以JDK1.7為准)
1 //無參構造函數 2 public ArrayList() { 3 this(10); 4 }
到這里ArrayList數據時一個空數組。其size為0.
add()方法
調用add()方法,我們看一下add方法源碼:
1 //向ArrayList中添加一個元素 2 public boolean add(E e) { 3 ensureCapacityInternal(size + 1); // Increments modCount!! 4 elementData[size++] = e; 5 return true; 6 }
首先我們把參數‘hongten’傳遞給add()方法,該方法做了兩件事情:1.檢查數組大小,看看是否需要擴容。2.把對象加入到數組里面,然后返回。
這里的size我們知道是為1的。那么size+1=0+1=1作為參數傳遞給ensureCapacityInternal()方法。
ensureCapacityInternal()方法
我們來看看ensureCapacityInternal()方法:
1 //默認數組大小為10 2 private static final int DEFAULT_CAPACITY = 10; 3 4 private void ensureCapacityInternal(int minCapacity) { 5 //初始化時候,elementData是為空數組對象EMPTY_ELEMENTDATA,所以會去設置minCapacity的值 6 if (elementData == EMPTY_ELEMENTDATA) { 7 //設置minCapacity值,比較minCapacity和默認容量(DEFAULT_CAPACITY=10) 8 //把最大值賦值給minCapacity 9 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 10 } 11 //確定明確的容量大小 12 ensureExplicitCapacity(minCapacity); 13 }
原來在這個方法里面用到了DEFAULT_CAPACITY=10,所以,最后的minCapacity=10,並且作為參數傳遞給了ensureExplicitCapacity()方法。
ensureExplicitCapacity()方法
我們接着來看看ensureExplicitCapacity()方法:
1 //確定明確的容量大小 2 private void ensureExplicitCapacity(int minCapacity) { 3 modCount++; 4 5 // overflow-conscious code 6 if (minCapacity - elementData.length > 0) 7 grow(minCapacity); 8 }
modCount是繼承自AbstractList的,主要用於Iterator()和listIterator()方法。接下來是判斷minCapacity和elementData.length的大小,由於minCapacity=10,elementData現在還是空數組,所以elementData.length=0,所以是if(true)的情況。需要執行grow()方法。
grow()方法
那么grow()方法是什么樣的呢?
1 //最大數組大小=Integer.MAX_VALUE - 8 2 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 3 4 //擴容方法 5 private void grow(int minCapacity) { 6 //此時因為elementData為空數組,那么oldCapacity=0 7 int oldCapacity = elementData.length; 8 //newCapacity = 0 + (0 >> 1) = 0 + 0 = 0 9 int newCapacity = oldCapacity + (oldCapacity >> 1); 10 //0-10=-10<0 --> true 11 if (newCapacity - minCapacity < 0) 12 //newCapacity=10 13 newCapacity = minCapacity; 14 //10-MAX_ARRAY_SIZE = -Integer.MAX_VALUE+18<0 --> false 15 if (newCapacity - MAX_ARRAY_SIZE > 0) 16 newCapacity = hugeCapacity(minCapacity); 17 //現在才初始化數組 18 elementData = Arrays.copyOf(elementData, newCapacity); 19 }
我們發現JDK1.7.0_80和JDK1.5的區別在於此。他們初始化數組的時間不同。
JDK1.5在創建ArrayList的時候就初始化了數組,然而,JDK1.7是在這里開始初始化數組。
Arrays.copyOf()方法
那么接下來的Arrays.copyOf()方法就值得我們去研究了:
1 public static <T> T[] copyOf(T[] original, int newLength) { 2 //elementData此時還是空數組,newLength=10,original.getClass()-->為elementData數組類對象Object[] 3 return (T[]) copyOf(original, newLength, original.getClass()); 4 } 5 6 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { 7 //因為newType = Object[].class -->true 8 //所以copy= new Object[10]; 9 T[] copy = ((Object)newType == (Object)Object[].class) 10 ? (T[]) new Object[newLength] 11 : (T[]) Array.newInstance(newType.getComponentType(), newLength); 12 //original為空數組, copy是長度為10的數組 13 //將指定源數組中的數組從指定位置復制到目標數組的指定位置 14 System.arraycopy(original, 0, copy, 0, 15 Math.min(original.length, newLength)); 16 return copy; 17 }
copyOf()方法返回一個長度為10的數組,然后賦值給elementData,完成ArrayList里面數組的初始化工作。
這就完成了add()方法里面的第一步操作。
第二步操作是:
數組size++,然后把參數加入到數組里面,然后返回,完成往ArrayList里面添加元素的操作。
那么這個時候的size也就是我們看到的輸出結果1.
remove()方法
再來看看ArrayList里面的remove()刪除操作
1 //刪除指定索引值所在的對象,並返回所刪除的對象 2 public E remove(int index) { 3 //先檢查傳入的索引是否合法 4 rangeCheck(index); 5 6 modCount++; 7 //獲取到指引所在對應的數組對象 8 E oldValue = elementData(index); 9 10 int numMoved = size - index - 1; 11 if (numMoved > 0) 12 //所有對象向前移動 13 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 14 //把數組最后一個元素置空,以便java虛擬機回收 15 elementData[--size] = null; // clear to let GC do its work 16 17 return oldValue; 18 }
在進行刪除操作的時候,需要把指引所指向的對象刪除掉,並且把該對象以后的元素向前移動,最后返回被刪除的元素。
三.詳解Vector
先來看看Vector的源碼
1 public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { 2 3 //Vector和ArrayList一樣,底層基於該數組實現 4 protected Object[] elementData; 5 //這個相當於ArrayList里面的size 6 protected int elementCount; 7 //當Vector的大小大於其容量時,Vector的容量自動增加的量。 8 protected int capacityIncrement; 9 10 //帶容量和容量自動增加量的參數的構造函數 11 public Vector(int initialCapacity, int capacityIncrement) { 12 super(); 13 if (initialCapacity < 0) 14 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); 15 this.elementData = new Object[initialCapacity]; 16 this.capacityIncrement = capacityIncrement; 17 } 18 19 //給定容量的構造函數 20 public Vector(int initialCapacity) { 21 this(initialCapacity, 0); 22 } 23 24 //無參構造函數 25 public Vector() { 26 //初始化數組,大小為10 27 this(10); 28 } 29 30 //包含Collection對象的構造函數 31 public Vector(Collection<? extends E> c) { 32 elementData = c.toArray(); 33 elementCount = elementData.length; 34 // c.toArray might (incorrectly) not return Object[] (see 6260652) 35 if (elementData.getClass() != Object[].class) 36 elementData = Arrays.copyOf(elementData, elementCount, Object[].class); 37 } 38 39 //將當期容量值設置為實際元素個數 40 public synchronized void trimToSize() { 41 modCount++; 42 int oldCapacity = elementData.length; 43 if (elementCount < oldCapacity) { 44 elementData = Arrays.copyOf(elementData, elementCount); 45 } 46 } 47 48 // 49 public synchronized void ensureCapacity(int minCapacity) { 50 if (minCapacity > 0) { 51 modCount++; 52 ensureCapacityHelper(minCapacity); 53 } 54 } 55 56 //維護數組大小 57 private void ensureCapacityHelper(int minCapacity) { 58 // overflow-conscious code 59 if (minCapacity - elementData.length > 0) 60 //數組擴容 61 grow(minCapacity); 62 } 63 64 //數組最大size 65 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 66 67 //數組擴容 68 private void grow(int minCapacity) { 69 // overflow-conscious code 70 int oldCapacity = elementData.length; 71 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); 72 if (newCapacity - minCapacity < 0) 73 newCapacity = minCapacity; 74 if (newCapacity - MAX_ARRAY_SIZE > 0) 75 newCapacity = hugeCapacity(minCapacity); 76 elementData = Arrays.copyOf(elementData, newCapacity); 77 } 78 79 private static int hugeCapacity(int minCapacity) { 80 if (minCapacity < 0) // overflow 81 throw new OutOfMemoryError(); 82 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 83 } 84 85 //設置數組大小 86 public synchronized void setSize(int newSize) { 87 modCount++; 88 if (newSize > elementCount) { 89 ensureCapacityHelper(newSize); 90 } else { 91 for (int i = newSize; i < elementCount; i++) { 92 elementData[i] = null; 93 } 94 } 95 elementCount = newSize; 96 } 97 98 //獲取數組長度 99 public synchronized int capacity() { 100 return elementData.length; 101 } 102 103 //獲取大小 104 public synchronized int size() { 105 return elementCount; 106 } 107 108 //判斷是否為空 109 public synchronized boolean isEmpty() { 110 return elementCount == 0; 111 } 112 113 //是否包含某個元素/對象 114 public boolean contains(Object o) { 115 return indexOf(o, 0) >= 0; 116 } 117 118 //正向查詢,如果找到,則返回對象的索引值 119 public int indexOf(Object o) { 120 return indexOf(o, 0); 121 } 122 123 //正向查詢,如果找到,則返回對象的索引值 124 public synchronized int indexOf(Object o, int index) { 125 if (o == null) { 126 for (int i = index; i < elementCount; i++) 127 if (elementData[i] == null) 128 return i; 129 } else { 130 for (int i = index; i < elementCount; i++) 131 if (o.equals(elementData[i])) 132 return i; 133 } 134 return -1; 135 } 136 137 //反向查詢,如果找到,則返回對象的索引值 138 public synchronized int lastIndexOf(Object o) { 139 return lastIndexOf(o, elementCount - 1); 140 } 141 142 //反向查詢,如果找到,則返回對象的索引值 143 public synchronized int lastIndexOf(Object o, int index) { 144 if (index >= elementCount) 145 throw new IndexOutOfBoundsException(index + " >= " + elementCount); 146 147 if (o == null) { 148 for (int i = index; i >= 0; i--) 149 if (elementData[i] == null) 150 return i; 151 } else { 152 for (int i = index; i >= 0; i--) 153 if (o.equals(elementData[i])) 154 return i; 155 } 156 return -1; 157 } 158 159 //根據索引移除對象 160 public synchronized void removeElementAt(int index) { 161 modCount++; 162 if (index >= elementCount) { 163 throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); 164 } else if (index < 0) { 165 throw new ArrayIndexOutOfBoundsException(index); 166 } 167 int j = elementCount - index - 1; 168 if (j > 0) { 169 System.arraycopy(elementData, index + 1, elementData, index, j); 170 } 171 elementCount--; 172 elementData[elementCount] = null; /* to let gc do its work */ 173 } 174 175 //在給定的索引里插入對象 176 public synchronized void insertElementAt(E obj, int index) { 177 modCount++; 178 if (index > elementCount) { 179 throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); 180 } 181 ensureCapacityHelper(elementCount + 1); 182 System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); 183 elementData[index] = obj; 184 elementCount++; 185 } 186 187 //添加元素 188 public synchronized void addElement(E obj) { 189 modCount++; 190 ensureCapacityHelper(elementCount + 1); 191 elementData[elementCount++] = obj; 192 } 193 194 //直接刪除掉索引指向的元素 195 public synchronized boolean removeElement(Object obj) { 196 modCount++; 197 int i = indexOf(obj); 198 if (i >= 0) { 199 removeElementAt(i); 200 return true; 201 } 202 return false; 203 } 204 205 //移除所有元素 206 public synchronized void removeAllElements() { 207 modCount++; 208 // Let gc do its work 209 for (int i = 0; i < elementCount; i++) 210 elementData[i] = null; 211 212 elementCount = 0; 213 } 214 215 @SuppressWarnings("unchecked") 216 E elementData(int index) { 217 return (E) elementData[index]; 218 } 219 220 //根據索引值查詢對象 221 public synchronized E get(int index) { 222 if (index >= elementCount) 223 throw new ArrayIndexOutOfBoundsException(index); 224 225 return elementData(index); 226 } 227 228 //根據索引值,把element設置為該索引所對應的值 229 public synchronized E set(int index, E element) { 230 if (index >= elementCount) 231 throw new ArrayIndexOutOfBoundsException(index); 232 233 E oldValue = elementData(index); 234 elementData[index] = element; 235 return oldValue; 236 } 237 238 //向Vector中添加一個元素 239 public synchronized boolean add(E e) { 240 modCount++;//繼承自AbstactList 241 //維護數組大小 242 ensureCapacityHelper(elementCount + 1); 243 //把元素加入到數組中,數組大小加1. 244 elementData[elementCount++] = e; 245 return true; 246 } 247 248 //刪除對象,並返回是否刪除成功 249 public boolean remove(Object o) { 250 return removeElement(o); 251 } 252 253 //根據指定的索引值添加對象 254 public void add(int index, E element) { 255 insertElementAt(element, index); 256 } 257 258 //刪除指定索引值所在的對象,並返回所刪除的對象 259 public synchronized E remove(int index) { 260 modCount++; 261 if (index >= elementCount) 262 throw new ArrayIndexOutOfBoundsException(index); 263 E oldValue = elementData(index); 264 265 int numMoved = elementCount - index - 1; 266 if (numMoved > 0) 267 //所有對象向前移動 268 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 269 //把數組最后一個元素置空,以便java虛擬機回收 270 elementData[--elementCount] = null; // Let gc do its work 271 272 return oldValue; 273 } 274 275 //把數組置空 276 public void clear() { 277 removeAllElements(); 278 } 279 280 // Bulk Operations 281 282 //添加包含Collection的元素對象 283 public synchronized boolean containsAll(Collection<?> c) { 284 return super.containsAll(c); 285 } 286 287 //添加包含Collection的元素對象 288 public synchronized boolean addAll(Collection<? extends E> c) { 289 modCount++; 290 Object[] a = c.toArray(); 291 int numNew = a.length; 292 ensureCapacityHelper(elementCount + numNew); 293 System.arraycopy(a, 0, elementData, elementCount, numNew); 294 elementCount += numNew; 295 return numNew != 0; 296 } 297 298 //獲取子list對象 299 public synchronized List<E> subList(int fromIndex, int toIndex) { 300 return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); 301 } 302 303 //刪除某一個區域對象 304 protected synchronized void removeRange(int fromIndex, int toIndex) { 305 modCount++; 306 int numMoved = elementCount - toIndex; 307 System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); 308 309 // Let gc do its work 310 int newElementCount = elementCount - (toIndex - fromIndex); 311 while (elementCount != newElementCount) 312 elementData[--elementCount] = null; 313 } 314 315 //用於迭代Vector 316 public synchronized ListIterator<E> listIterator() { 317 return new ListItr(0); 318 } 319 320 //用於迭代Vector 321 public synchronized Iterator<E> iterator() { 322 return new Itr(); 323 } 324 }
我們可以看到Vector和ArrayList是否類似,Vector是一個可變大小的數組。它提供了很多方法:size,isEmpty, get, set, listIterator,add,addAll等等。
和ArrayList相比,不同之處在於Vector的很多方法都加了關鍵字synchronized,使得Vector具有了同步功能,支持並發。
我們來分析一下下面的代碼:
當我們創建一個Vector的時候,其數組長度為10的數組,但是因為里面沒有任何元素,所以我們看到第一次輸出為0。當我們往數組里面添加一個元素‘hongten’后,其數組含有的元素個數變為1.
1 List<String> myVactor = new Vector<String>(); 2 System.out.println(myVactor.size());//輸出:0 3 myVactor.add("hongten"); 4 System.out.println(myVactor.size());//輸出:1
Vector構造函數
來看看Vector的構造函數:
1 //Vector和ArrayList一樣,底層基於該數組實現 2 protected Object[] elementData; 3 //這個相當於ArrayList里面的size 4 protected int elementCount; 5 //當Vector的大小大於其容量時,Vector的容量自動增加的量。 6 protected int capacityIncrement; 7 8 //帶容量和容量自動增加量的參數的構造函數 9 public Vector(int initialCapacity, int capacityIncrement) { 10 super(); 11 if (initialCapacity < 0) 12 throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); 13 //初始化數組 14 this.elementData = new Object[initialCapacity]; 15 this.capacityIncrement = capacityIncrement; 16 } 17 18 //給定容量的構造函數 19 public Vector(int initialCapacity) { 20 this(initialCapacity, 0); 21 } 22 23 //無參構造函數 24 public Vector() { 25 //初始化數組,大小為10 26 this(10); 27 }
我們可以看到,當我們new Vector()的時候,vector里面的數組就已經被初始化了,並且數組的長度為10.
add()方法
接下來調用add()方法:
1 //向Vector中添加一個元素 2 public synchronized boolean add(E e) { 3 modCount++;//繼承自AbstactList 4 //維護數組大小 5 ensureCapacityHelper(elementCount + 1); 6 //把元素加入到數組中,數組大小加1. 7 elementData[elementCount++] = e; 8 return true; 9 }
add方法是向Vector里面添加一個元素,並且使用了關鍵字synchronized,支持並發。和ArrayList類似,1.維護數組大小。2.把元素添加到數組中,然后返回
ensureCapacityHelper()方法
調用ensureCapacityHelper()方法:
1 //維護數組大小 2 private void ensureCapacityHelper(int minCapacity) { 3 //minCapacity - elementData.length = 1 - 10 = -9 < 0 --> false 4 if (minCapacity - elementData.length > 0) 5 //數組擴容 6 grow(minCapacity); 7 }
可以看到這里,在默認情況下,添加一條記錄進入到vector的時候,數組並不需要擴容。到這里,add方法的第一步完成。
接下來第二步:把元素添加到數組中,數組大小加1.並返回,完成添加元素操作。
grow()方法
當我們往vector數組里面一直加入數據,把默認的第10個數據都加滿的時候,那么這個時候就需要調用grow()方法了
1 //數組最大size 2 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 3 4 //數組擴容 5 private void grow(int minCapacity) { 6 //此時的minCapacity值為11 7 //oldCapacity= 10 8 int oldCapacity = elementData.length; 9 //因為此時capacityIncrement是為0的 10 //所以(capacityIncrement > 0) ? capacityIncrement : oldCapacity = (0>0)?0:10=0 11 //newCapacity=10+(0)=10 12 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); 13 //10-11=-1<0 --> true 14 if (newCapacity - minCapacity < 0) 15 //newCapacity = 11 16 newCapacity = minCapacity; 17 if (newCapacity - MAX_ARRAY_SIZE > 0) 18 newCapacity = hugeCapacity(minCapacity); 19 elementData = Arrays.copyOf(elementData, newCapacity); 20 } 21 22 private static int hugeCapacity(int minCapacity) { 23 if (minCapacity < 0) // overflow 24 throw new OutOfMemoryError(); 25 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 26 }
remove()方法
remove()方法和Arraylist里面的方法差不多,區別在於多了關鍵字synchronized。
1 //刪除指定索引值所在的對象,並返回所刪除的對象 2 public synchronized E remove(int index) { 3 modCount++; 4 if (index >= elementCount) 5 throw new ArrayIndexOutOfBoundsException(index); 6 E oldValue = elementData(index); 7 8 int numMoved = elementCount - index - 1; 9 if (numMoved > 0) 10 //所有對象向前移動 11 System.arraycopy(elementData, index + 1, elementData, index, numMoved); 12 //把數組最后一個元素置空,以便java虛擬機回收 13 elementData[--elementCount] = null; // Let gc do its work 14 15 return oldValue; 16 }
四.詳解LinkedList
先來看看LinkedList的源碼
1 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { 2 transient int size = 0; 3 4 //第一個元素的引用 5 transient Node<E> first; 6 7 //最后一個元素的引用 8 transient Node<E> last; 9 10 //無參構造函數 11 public LinkedList() { 12 } 13 14 //包含一個Collection的構造函數 15 public LinkedList(Collection<? extends E> c) { 16 this(); 17 addAll(c); 18 } 19 20 //在鏈表頭部創建鏈接 21 private void linkFirst(E e) { 22 final Node<E> f = first; 23 final Node<E> newNode = new Node<>(null, e, f); 24 first = newNode; 25 if (f == null) 26 last = newNode; 27 else 28 f.prev = newNode; 29 size++; 30 modCount++; 31 } 32 33 //在鏈表尾部創建鏈接 34 void linkLast(E e) { 35 final Node<E> l = last; 36 final Node<E> newNode = new Node<>(l, e, null); 37 last = newNode; 38 if (l == null) 39 first = newNode; 40 else 41 l.next = newNode; 42 size++; 43 modCount++; 44 } 45 46 /** 47 * Inserts element e before non-null Node succ. 48 */ 49 void linkBefore(E e, Node<E> succ) { 50 // assert succ != null; 51 final Node<E> pred = succ.prev; 52 final Node<E> newNode = new Node<>(pred, e, succ); 53 succ.prev = newNode; 54 if (pred == null) 55 first = newNode; 56 else 57 pred.next = newNode; 58 size++; 59 modCount++; 60 } 61 62 //刪除鏈表中第一個鏈接 63 private E unlinkFirst(Node<E> f) { 64 // assert f == first && f != null; 65 final E element = f.item; 66 final Node<E> next = f.next; 67 f.item = null; 68 f.next = null; // help GC 69 first = next; 70 if (next == null) 71 last = null; 72 else 73 next.prev = null; 74 size--; 75 modCount++; 76 return element; 77 } 78 79 //刪除鏈表中最后一個鏈接 80 private E unlinkLast(Node<E> l) { 81 // assert l == last && l != null; 82 final E element = l.item; 83 final Node<E> prev = l.prev; 84 l.item = null; 85 l.prev = null; // help GC 86 last = prev; 87 if (prev == null) 88 first = null; 89 else 90 prev.next = null; 91 size--; 92 modCount++; 93 return element; 94 } 95 96 //刪除鏈表給定的元素鏈接 97 E unlink(Node<E> x) { 98 // assert x != null; 99 final E element = x.item; 100 final Node<E> next = x.next; 101 final Node<E> prev = x.prev; 102 103 if (prev == null) { 104 first = next; 105 } else { 106 prev.next = next; 107 x.prev = null; 108 } 109 110 if (next == null) { 111 last = prev; 112 } else { 113 next.prev = prev; 114 x.next = null; 115 } 116 117 x.item = null; 118 size--; 119 modCount++; 120 return element; 121 } 122 123 //獲取頭部元素 124 public E getFirst() { 125 final Node<E> f = first; 126 if (f == null) 127 throw new NoSuchElementException(); 128 return f.item; 129 } 130 131 //獲取尾部元素 132 public E getLast() { 133 final Node<E> l = last; 134 if (l == null) 135 throw new NoSuchElementException(); 136 return l.item; 137 } 138 139 //移除頭部元素 140 public E removeFirst() { 141 final Node<E> f = first; 142 if (f == null) 143 throw new NoSuchElementException(); 144 return unlinkFirst(f); 145 } 146 147 //移除尾部元素 148 public E removeLast() { 149 final Node<E> l = last; 150 if (l == null) 151 throw new NoSuchElementException(); 152 return unlinkLast(l); 153 } 154 155 //添加一個元素在鏈表頭部 156 public void addFirst(E e) { 157 linkFirst(e); 158 } 159 160 //添加一個元素到鏈表尾部 161 public void addLast(E e) { 162 linkLast(e); 163 } 164 165 //判斷是否包含某個元素 166 public boolean contains(Object o) { 167 return indexOf(o) != -1; 168 } 169 170 //獲取鏈表大小 171 public int size() { 172 return size; 173 } 174 175 //添加元素 176 public boolean add(E e) { 177 //把該元素放到鏈表最后面 178 linkLast(e); 179 return true; 180 } 181 182 //移除鏈表中一個給定的元素對象 183 public boolean remove(Object o) { 184 if (o == null) { 185 for (Node<E> x = first; x != null; x = x.next) { 186 if (x.item == null) { 187 unlink(x); 188 return true; 189 } 190 } 191 } else { 192 for (Node<E> x = first; x != null; x = x.next) { 193 if (o.equals(x.item)) { 194 unlink(x); 195 return true; 196 } 197 } 198 } 199 return false; 200 } 201 202 //添加一個包含Collection的元素 203 public boolean addAll(Collection<? extends E> c) { 204 return addAll(size, c); 205 } 206 207 //在給定的索引下面添加一個包含Collection的元素 208 public boolean addAll(int index, Collection<? extends E> c) { 209 checkPositionIndex(index); 210 211 Object[] a = c.toArray(); 212 int numNew = a.length; 213 if (numNew == 0) 214 return false; 215 216 Node<E> pred, succ; 217 if (index == size) { 218 succ = null; 219 pred = last; 220 } else { 221 succ = node(index); 222 pred = succ.prev; 223 } 224 225 for (Object o : a) { 226 @SuppressWarnings("unchecked") 227 E e = (E) o; 228 Node<E> newNode = new Node<>(pred, e, null); 229 if (pred == null) 230 first = newNode; 231 else 232 pred.next = newNode; 233 pred = newNode; 234 } 235 236 if (succ == null) { 237 last = pred; 238 } else { 239 pred.next = succ; 240 succ.prev = pred; 241 } 242 243 size += numNew; 244 modCount++; 245 return true; 246 } 247 248 //清除鏈表 249 public void clear() { 250 for (Node<E> x = first; x != null;) { 251 Node<E> next = x.next; 252 x.item = null; 253 x.next = null; 254 x.prev = null; 255 x = next; 256 } 257 first = last = null; 258 size = 0; 259 modCount++; 260 } 261 262 // Positional Access Operations 263 264 //根據索引獲取元素 265 public E get(int index) { 266 checkElementIndex(index); 267 return node(index).item; 268 } 269 270 //根據索引設置索引所指向的對象的值 271 public E set(int index, E element) { 272 checkElementIndex(index); 273 Node<E> x = node(index); 274 E oldVal = x.item; 275 x.item = element; 276 return oldVal; 277 } 278 279 //根據索引添加元素 280 public void add(int index, E element) { 281 checkPositionIndex(index); 282 283 if (index == size) 284 linkLast(element); 285 else 286 linkBefore(element, node(index)); 287 } 288 289 //根據索引移除元素 290 public E remove(int index) { 291 checkElementIndex(index); 292 return unlink(node(index)); 293 } 294 295 //判斷所給索引是否合法 296 private boolean isElementIndex(int index) { 297 return index >= 0 && index < size; 298 } 299 300 //判斷所給索引是否為第一個/最后一個 301 private boolean isPositionIndex(int index) { 302 return index >= 0 && index <= size; 303 } 304 305 private void checkElementIndex(int index) { 306 if (!isElementIndex(index)) 307 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 308 } 309 310 private void checkPositionIndex(int index) { 311 if (!isPositionIndex(index)) 312 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 313 } 314 315 Node<E> node(int index) { 316 if (index < (size >> 1)) { 317 Node<E> x = first; 318 for (int i = 0; i < index; i++) 319 x = x.next; 320 return x; 321 } else { 322 Node<E> x = last; 323 for (int i = size - 1; i > index; i--) 324 x = x.prev; 325 return x; 326 } 327 } 328 329 public E poll() { 330 final Node<E> f = first; 331 return (f == null) ? null : unlinkFirst(f); 332 } 333 334 //Queue里面offer()方法 335 public boolean offer(E e) { 336 return add(e); 337 } 338 339 //Deque里面offerFirst()方法 340 public boolean offerFirst(E e) { 341 addFirst(e); 342 return true; 343 } 344 345 //Deque里面offerLast()方法 346 public boolean offerLast(E e) { 347 addLast(e); 348 return true; 349 } 350 351 public ListIterator<E> listIterator(int index) { 352 checkPositionIndex(index); 353 return new ListItr(index); 354 } 355 356 private static class Node<E> { 357 E item; 358 Node<E> next; 359 Node<E> prev; 360 361 Node(Node<E> prev, E element, Node<E> next) { 362 this.item = element; 363 this.next = next; 364 this.prev = prev; 365 } 366 } 367 }
我們可以看到LinkedList繼承了AbstractSequentialList,並且實現了List, Deque, Cloneable, Serializable接口,LinkedList底層是基於鏈表實現的。
所以我們必須去了解一下鏈表的數據結構。
在LinkedList里面定義了一個私有靜態內部類Node,可以看到Node有三個成員變量,item, next, prev.從字面上理解為本身, 下一個元素,前一個元素。
1 private static class Node<E> { 2 //本身 3 E item; 4 //下一個元素 5 Node<E> next; 6 //前一個元素 7 Node<E> prev; 8 9 Node(Node<E> prev, E element, Node<E> next) { 10 this.item = element; 11 this.next = next; 12 this.prev = prev; 13 } 14 }
add()方法
來看看add()方法,該方法是直接把元素放到鏈表尾部,然后返回。
1 //添加元素 2 public boolean add(E e) { 3 //把該元素放到鏈表最后面 4 linkLast(e); 5 return true; 6 }
linkLast()方法
把對象加入到鏈表的尾部,然后鏈表大小+1
1 // 第一個元素的引用 2 transient Node<E> first; 3 4 // 最后一個元素的引用 5 transient Node<E> last; 6 7 //在鏈表尾部創建鏈接 8 void linkLast(E e) { 9 //獲取最后一個元素 10 final Node<E> l = last; 11 //創建一個一個Node對象,參數(前,本,后) 12 //前:指向鏈表最后一個元素,即新加入的元素的上一個元素 13 //本:指的就是新加入元素本身 14 //后:因為新加入的元素本身就是在鏈表最后面加入,所以,后面沒有元素,則為null 15 final Node<E> newNode = new Node<>(l, e, null); 16 //把last引用指向新創建的對象上面 17 last = newNode; 18 //如果在鏈表為空的情況下,first=last=null 19 if (l == null) 20 //那么第一個就是最新創建的元素 21 first = newNode; 22 else 23 //把鏈表最后元素的next指向創建的新元素的引用 24 l.next = newNode; 25 //鏈表大小+1 26 size++; 27 modCount++; 28 }
remove()方法
根據索引移除對象,首先要判斷索引是否合法,如果合法,則移除索引所指對象。
1 //根據索引移除元素 2 public E remove(int index) { 3 checkElementIndex(index); 4 return unlink(node(index)); 5 }
unlink()方法
unlink()方法的目的就是把即將被刪除的元素從鏈表里面拿出來,並且維護好鏈表狀態。
1 //刪除鏈表給定的元素鏈接 2 E unlink(Node<E> x) { 3 //該元素本身 4 final E element = x.item; 5 //該元素下一個元素 6 final Node<E> next = x.next; 7 //該元素上一個元素 8 final Node<E> prev = x.prev; 9 10 //如果該元素本身就是第一個元素,即鏈表頭部 11 if (prev == null) { 12 //那么就把first指向下一個元素引用 13 first = next; 14 } else { 15 //把前一個元素的next指向該元素的下一個元素,即跳過該元素 16 //因為該元素馬上要被刪除掉了 17 prev.next = next; 18 //把該元素前一個元素引用置空 19 x.prev = null; 20 } 21 22 //如果該元素本身就是最后一個元素,即鏈表尾部 23 if (next == null) { 24 //那么把last指向前一個元素引用 25 last = prev; 26 } else { 27 //把下一個元素的prev指向該元素的上一個元素,也是跳過該元素(即將被刪) 28 next.prev = prev; 29 //把該元素下一個元素引用置空 30 x.next = null; 31 } 32 33 //把該元素本身置空 34 x.item = null; 35 //鏈表大小-1 36 size--; 37 modCount++; 38 //返回該元素 39 return element; 40 }
五.在並發情況下,怎樣使用它們
類部類MyThread繼承了Thread類,並且重寫了run()方法。在MyThread里面定義了4個static變量,這些變量是為了存放線程在運行過程中向里面添加元素的值。
1 package com.b510.test; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.LinkedList; 6 import java.util.List; 7 import java.util.Vector; 8 import java.util.concurrent.ExecutorService; 9 import java.util.concurrent.Executors; 10 import java.util.concurrent.TimeUnit; 11 12 /** 13 * @author Hongwei 14 * @created 28 Aug 2018 15 */ 16 public class MyListTest { 17 18 public static void main(String[] args) throws Exception { 19 // 創建線程池 20 ExecutorService exec = Executors.newCachedThreadPool(); 21 exec.execute(new MyThread()); 22 exec.execute(new MyThread()); 23 exec.execute(new MyThread()); 24 exec.execute(new MyThread()); 25 exec.execute(new MyThread()); 26 exec.execute(new MyThread()); 27 exec.execute(new MyThread()); 28 exec.execute(new MyThread()); 29 exec.execute(new MyThread()); 30 31 System.out.println("begin..."); 32 TimeUnit.SECONDS.sleep(2); 33 exec.shutdownNow(); 34 35 List<Integer> myArrayList = MyThread.myArrayList; 36 List<Integer> myLinkedList = MyThread.myLinkedList; 37 List<Integer> myVector = MyThread.myVector; 38 List<Integer> mySynchronziedArrayList = MyThread.mySynchronziedArrayList; 39 if (myArrayList != null && myArrayList.size() > 0) { 40 System.out.println("ArrayList: " + myArrayList); 41 } 42 if (myVector != null && myVector.size() > 0) { 43 System.out.println("vector: " + myVector); 44 } 45 if (mySynchronziedArrayList != null && mySynchronziedArrayList.size() > 0) { 46 System.out.println("SynchronziedArrayList: " + mySynchronziedArrayList); 47 } 48 if (myLinkedList != null && myLinkedList.size() > 0) { 49 System.out.println("linkedList: " + myLinkedList); 50 } 51 52 System.out.println("end..."); 53 54 } 55 } 56 57 class MyThread extends Thread { 58 59 //arrayList,不支持並發 60 static List<Integer> myArrayList = new ArrayList<Integer>(); 61 //linkedList 62 static List<Integer> myLinkedList = new LinkedList<Integer>(); 63 //Vector,線程安全,支持並發 64 static List<Integer> myVector = new Vector<Integer>(); 65 //Connections.synchonizedList,線程安全,支持並發 66 static List<Integer> mySynchronziedArrayList = Collections.synchronizedList(new ArrayList<Integer>()); 67 68 public void run() { 69 for (int i = 0; i < 10; i++) { 70 try { 71 TimeUnit.MILLISECONDS.sleep(2); 72 System.out.println(Thread.currentThread().getName() + " add value " + i); 73 myArrayList.add(i); 74 myVector.add(i); 75 mySynchronziedArrayList.add(i); 76 myLinkedList.add(i); 77 78 } catch (InterruptedException e) { 79 e.printStackTrace(); 80 } 81 } 82 } 83 } 84 /* 85 output: 86 begin... 87 pool-1-thread-1 add value 0 88 pool-1-thread-3 add value 0 89 pool-1-thread-8 add value 0 90 pool-1-thread-4 add value 0 91 pool-1-thread-7 add value 0 92 pool-1-thread-6 add value 0 93 pool-1-thread-2 add value 0 94 pool-1-thread-5 add value 0 95 pool-1-thread-9 add value 0 96 pool-1-thread-5 add value 1 97 pool-1-thread-4 add value 1 98 pool-1-thread-6 add value 1 99 pool-1-thread-8 add value 1 100 pool-1-thread-2 add value 1 101 pool-1-thread-3 add value 1 102 pool-1-thread-7 add value 1 103 pool-1-thread-1 add value 1 104 pool-1-thread-9 add value 1 105 pool-1-thread-7 add value 2 106 pool-1-thread-3 add value 2 107 pool-1-thread-5 add value 2 108 pool-1-thread-2 add value 2 109 pool-1-thread-8 add value 2 110 pool-1-thread-6 add value 2 111 pool-1-thread-4 add value 2 112 pool-1-thread-1 add value 2 113 pool-1-thread-9 add value 2 114 pool-1-thread-8 add value 3 115 pool-1-thread-1 add value 3 116 pool-1-thread-2 add value 3 117 pool-1-thread-3 add value 3 118 pool-1-thread-7 add value 3 119 pool-1-thread-5 add value 3 120 pool-1-thread-4 add value 3 121 pool-1-thread-6 add value 3 122 pool-1-thread-9 add value 3 123 pool-1-thread-3 add value 4 124 pool-1-thread-7 add value 4 125 pool-1-thread-4 add value 4 126 pool-1-thread-8 add value 4 127 pool-1-thread-2 add value 4 128 pool-1-thread-6 add value 4 129 pool-1-thread-1 add value 4 130 pool-1-thread-5 add value 4 131 pool-1-thread-9 add value 4 132 pool-1-thread-1 add value 5 133 pool-1-thread-6 add value 5 134 pool-1-thread-2 add value 5 135 pool-1-thread-3 add value 5 136 pool-1-thread-7 add value 5 137 pool-1-thread-5 add value 5 138 pool-1-thread-8 add value 5 139 pool-1-thread-4 add value 5 140 pool-1-thread-9 add value 5 141 pool-1-thread-8 add value 6 142 pool-1-thread-5 add value 6 143 pool-1-thread-6 add value 6 144 pool-1-thread-1 add value 6 145 pool-1-thread-2 add value 6 146 pool-1-thread-3 add value 6 147 pool-1-thread-7 add value 6 148 pool-1-thread-4 add value 6 149 pool-1-thread-9 add value 6 150 pool-1-thread-8 add value 7 151 pool-1-thread-3 add value 7 152 pool-1-thread-1 add value 7 153 pool-1-thread-6 add value 7 154 pool-1-thread-7 add value 7 155 pool-1-thread-2 add value 7 156 pool-1-thread-4 add value 7 157 pool-1-thread-5 add value 7 158 pool-1-thread-9 add value 7 159 pool-1-thread-1 add value 8 160 pool-1-thread-6 add value 8 161 pool-1-thread-3 add value 8 162 pool-1-thread-7 add value 8 163 pool-1-thread-2 add value 8 164 pool-1-thread-5 add value 8 165 pool-1-thread-8 add value 8 166 pool-1-thread-4 add value 8 167 pool-1-thread-9 add value 8 168 pool-1-thread-1 add value 9 169 pool-1-thread-4 add value 9 170 pool-1-thread-7 add value 9 171 pool-1-thread-3 add value 9 172 pool-1-thread-2 add value 9 173 pool-1-thread-8 add value 9 174 pool-1-thread-6 add value 9 175 pool-1-thread-5 add value 9 176 pool-1-thread-9 add value 9 177 ArrayList: [null, null, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9] 178 vector: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9] 179 SynchronziedArrayList: [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9] 180 Exception in thread "main" java.lang.NullPointerException 181 at java.util.LinkedList$ListItr.next(LinkedList.java:891) 182 at java.util.AbstractCollection.toString(AbstractCollection.java:457) 183 at java.lang.String.valueOf(String.java:2849) 184 at java.lang.StringBuilder.append(StringBuilder.java:128) 185 at com.b510.test.MyListTest.main(MyListTest.java:49) 186 */
之后我們從結果可以看到:
ArrayList:值可以為null,線程不安全,但是我們可以使用Collections.synchronzedList()方法使得一個ArrayList支持並發。
Vector:本身支持並發。
LinkedList:值可以為null,但是當我們調用時會拋出NullPointerException異常。
========================================================
More reading,and english is important.
I'm Hongten
大哥哥大姐姐,覺得有用打賞點哦!你的支持是我最大的動力。謝謝。
Hongten博客排名在100名以內。粉絲過千。
Hongten出品,必是精品。
E | hongtenzone@foxmail.com B | http://www.cnblogs.com/hongten
========================================================
我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=14s169zyimbmg
