2020-06-23
foreach刪除元素爲什麼會報錯
Math.max() 返回兩個數中大的那個,源碼裏是一個三元運算符
final:
final修飾的類不能被繼承。(Sting就是一個被final修飾的類,我們只能用,不用繼承)
final修飾的變量,是一個常量,只能賦值一次。
protected:
可以被子類,同package下類使用,不對外公開的訪問修飾符 在非static修飾下,子類不能通過new父類對象直接調用
default(不寫修飾符) 在一個包下的能訪問
transient :
瞬態 “不可序列化狀態”。
密碼,銀行卡號等敏感信息,爲了安全起見,不希望在網絡操作(主要涉及到序列化操作,本地序列化緩存也適用)中被傳輸。這些信息對應的變量就可以被定義爲transient類型。換句話說,這個字段的生命週期僅存於調用者的內存中。
List<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
System.out.println(arrayList);
for (Integer ele : arrayList) {
if (ele == 2) {arrayList.remove(ele);}
}
開始分析:
在編譯的時候編譯器會自動將對for這個關鍵字的使用轉化爲對目標的迭代器的使用
for(Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); 沒有i++){
Integer ele = iterator.next();
if(ele == 2)
list.remove(ele);
}
modCount:修改次數,被定義在ArrayList的父類AbstractList中 protected transient int modCount = 0
步驟1:.add 時,先判斷是否需要擴容,無論是否需要,modCount 都會++
三次add,modCount = 3, size=3;
步驟2:對Iterator進行初始化。返回一個Itr()類的一個實例(Itr是ArrayList的一個成員內部類)
int cursor;
int expectedModCount = modCount;
步驟3:循環條件的判斷
public boolean hasNext() {
return cursor != size();
}
步驟4:循環體內的.next
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public E next() {
checkForComodification();
int i = cursor;
...
...
...
cursor = i + 1;
...
}
步驟5:進行.remove操作
public boolean remove(Object o) {
if (o == null) {
...
fastRemove(index);
...
}
} else {
...
fastRemove(index);
...
}
}
...
}
private void fastRemove(int index) {
modCount++;
System.arraycopy(elementData, index+1, elementData, index, numMoved);
}
步驟6:remove完成後,開始下一次循環,執行 .next 判斷
此時:modCount == 4; 而expectedModCount == 3;
拋 java.util.ConcurrentModificationException
特殊情況:
若是在倒數第二個元素進行刪除操作時,經過前面的遍歷,next()方法將cursor增加至2,只比size=3少1。
在remove()操作時,size-1=2,hasNext()發現cursor=size,程序並沒有遍歷最後一個元素,程序正常終止。
如果要修改其他位置元素,都會拋異常
正確姿勢:
List<String> list = new ArrayList<>();
list.add("e1");
list.add("e2");
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if ("e1".equals(str)) {
iterator.remove();
}
}
迭代器的remove方法與集合的remove方法,最大的不同是,迭代器的remove方法中包括對遊標和expectedModCount的修正。
如果是多線程情況:
在使用iterator迭代的時候使用synchronized或者Lock進行同步;
使用併發容器CopyOnWriteArrayList代替ArrayList和Vector。