在遍歷 CopyOnWriteArrayList 時嘗試向同一列表新增元素,導致邏輯錯誤或例外。本文揭示根因並給出正確的遞迴式遍歷寫法。
Iterator<Long> iterator = supList.iterator();
while (iterator.hasNext()) {
Long s = iterator.next();
for (OrgDto o : list) {
if (o.getOrgId().equals(s) || o.getSupOrgId().equals(s)) {
nameList.add(o.getOrgName().trim());
supList.add(o.getOrgId()); // 修改正在遍歷的列表
}
}
}
CopyOnWriteArrayList 的迭代器是快照式的,遍歷過程中新增的元素不會被當前迭代器看到,導致遞迴查找子部門失效。
for (int i = 0; i < supList.size(); i++) {
Long s = supList.get(i);
for (OrgDto o : list) {
if (o.getOrgId().equals(s) || o.getSupOrgId().equals(s)) {
nameList.add(o.getOrgName().trim());
if (o.getSupOrgId().equals(s)) {
supList.add(o.getOrgId()); // 動態擴展,for 迴圈能感知 size 變化
}
}
}
}
for (int i=0; i<list.size(); i++) 每次迴圈都重新讀取 size(),新增元素會被後續迴圈處理。ConcurrentModificationException,同時實現了「廣度優先」的部門樹遞迴查找。正確輸出:10部門、12部門、13部門 —— 完整包含父部門及所有子孫部門。