學習的程序中遇到的一個問題, 下述代碼在嘗試remove其他元素的時候會出現例外,而在remove最后一個元素的時候,可以正常運行.
public class Main {
public static void main(String[] args) {
TreeMap<ModelWorker, String> map = new TreeMap<>();
map.put(new ModelWorker("張三", 18), "北京");
map.put(new ModelWorker("李四", 20), "上海");
map.put(new ModelWorker("王五", 35), "天津");
for (ModelWorker modelWorker : set) {
if ("張三".equals(modelWorker.getName())) {
map.remove(modelWorkermove(modelWorker)); // 這里嘗試remove最后一個物件
}
}
}
}
初步查找后得知,增強for和迭代器遍歷的程序中,直接用集合去remove以及其他修改集合的操作很容易出現問題.
之后Debug+翻原始碼分析了一下例外拋出的原因:
例外是在TreeMap中的一個繼承Iterator的抽象類中拋出的
next()方法原始碼如下
throw new ConcurrentModificationException();這行拋出例外原因顯然是因為if條件滿足modCount != expectedModCount 雖然不知道為什么jdk這樣設計的.這兩個變數在TreeMap類的成員變數中定義,沒搞懂是干嘛的.先繼續往下找找什么操作會導致這兩個變數的變化.
final Entry<K,V> nextEntry() {
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
next = successor(e);
lastReturned = e;
return e;
}
在remove()方法中發現呼叫了deleteEntry方法,該方法修改了導致例外拋出的條件的變數.
remove()方法導致變數值修改的核心部分
private void deleteEntry(Entry<K,V> p) {
modCount++;
size--;
// 省略沒用的
}
目前到這里,僅僅是大致上搞懂了為什么當使用集合的remove方法移除元素的時候會拋例外這點.還有一個問題有待解決,當移除最后一個元素的時候卻沒有拋出例外.
回頭檢查自己的代碼.增強for在編譯后會變成迭代器.反編譯后的代碼如下.
Iterator<ModelWorker> var3=set.iterator();
while(var3.hasNext()){
ModelWorker1 modelWorker=var3.next();
if("張三".equals(modelWorker.getName())){
map.remove(modelWorker);
}
}
從這里猜測會不會和代碼按順序執行有關,當remove最后一個元素后,下一行要執行的是hasNext,當hasNext執行完后回傳false后回圈會直接結束,而不進入next方法.并且例外可能只能是next方法拋出的.
所以順便查了下hasNext的原始碼.在此之中果然沒有拋出例外的陳述句.
hasNext()方法的原始碼
public final boolean hasNext() {
return next != null;
}
最后得到的結論就是,不要在增強for和迭代器遍歷中直接洗掉集合的元素.如果沒拋例外可能就是因為洗掉的是最后一個元素.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/199893.html
標籤:其他
上一篇:Java創建多執行緒的幾種方式
下一篇:shardbatis實作分表
