源碼如下
1 /** 2 * Removes the first occurrence of the specified element from this list, 3 * if it is present. If this list does not contain the element, it is 4 * unchanged. More formally, removes the element with the lowest index 5 * {@code i} such that 6 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> 7 * (if such an element exists). Returns {@code true} if this list 8 * contained the specified element (or equivalently, if this list 9 * changed as a result of the call). 10 * 11 * @param o element to be removed from this list, if present 12 * @return {@code true} if this list contained the specified element 13 */ 14 public boolean remove(Object o) { 15 //保存數組快照 16 Object[] snapshot = getArray(); 17 //獲得要查找對象的索引 18 //這個步驟無鎖,是為了減小鎖的粒度,提高並發度 19 int index = indexOf(o, snapshot, 0, snapshot.length); 20 //根據索引,從數組移除對象 21 return (index < 0) ? false : remove(o, snapshot, index); 22 } 23 24 /** 25 * static version of indexOf, to allow repeated calls without 26 * needing to re-acquire array each time. 27 * @param o element to search for 28 * @param elements the array 29 * @param index first index to search 30 * @param fence one past last index to search 31 * @return index of element, or -1 if absent 32 */ 33 private static int indexOf(Object o, Object[] elements, 34 int index, int fence) { 35 if (o == null) { 36 for (int i = index; i < fence; i++) 37 if (elements[i] == null) 38 return i; 39 } else { 40 for (int i = index; i < fence; i++) 41 if (o.equals(elements[i])) 42 return i; 43 } 44 return -1; 45 } 46 47 /** 48 * A version of remove(Object) using the strong hint that given 49 * recent snapshot contains o at the given index. 50 */ 51 private boolean remove(Object o, Object[] snapshot, int index) { 52 //進入這個方法有個默認條件,snapshot[index] == o 53 //而這里要考慮多線程的情況,即原有的數組可能已經被其他線程修改了,snapshot已經是過時的數據 54 final ReentrantLock lock = this.lock; 55 lock.lock(); 56 try { 57 //獲取最新數組數據 58 Object[] current = getArray(); 59 int len = current.length; 60 if (snapshot != current) findIndex: { 61 //考慮數組數據已經被其他線程修改了的情況,要重新定位index值 62 int prefix = Math.min(index, len); 63 //遍歷數組,從0到min(index, len),查找o的index 64 for (int i = 0; i < prefix; i++) { 65 if (current[i] != snapshot[i] && eq(o, current[i])) { 66 index = i; 67 break findIndex; 68 } 69 } 70 if (index >= len) 71 return false; 72 if (current[index] == o) 73 break findIndex; 74 index = indexOf(o, current, index, len); 75 if (index < 0) 76 return false; 77 } 78 79 //實際的刪除操作 80 Object[] newElements = new Object[len - 1]; 81 System.arraycopy(current, 0, newElements, 0, index); 82 System.arraycopy(current, index + 1, 83 newElements, index, 84 len - index - 1); 85 //用新數組替換舊數據 86 setArray(newElements); 87 return true; 88 } finally { 89 lock.unlock(); 90 } 91 }
不明白的地方在於從60行開始,到77行為止,也就是findIndex 這個功能。
其進入條件是快照數組和當前數組不相等,即其他線程對數組進行了修改的操作,所以需要重新查找index值。在我理解,只需要三行代碼就可以解決了,如下:
index = indexOf(o, current, 0, len);
if (index < 0)
return false;
這個方法是內部實現好的,直接調用飢渴獲取到current,即新數組的o對象對應的index值。
而源碼的那種實現我就不太懂了。尤其是循環里面的邏輯:
if (current[i] != snapshot[i] && eq(o, current[i]))
這個判斷是處於什么考慮,想破腦袋還是不明白。先記錄下來。
TODO