场景
最近需要去遍历修改树型数据中的叶子节点,数据结构如下:
"data": [
{
"id": 102528,
"name": "一级代理",
"children": [
{
"id": 480896,
"name": "二级代理",
"parentId": 102528,
"children": [
{
"id": 571520,
"name": "门店",
"parentId": 480896
}
]
}
]
}
]
于是乎写了一个简单的递归函数
private static List<Map<String, Objtect>> treeNode(Long id, List<Map<String, Object>> list) throws Exception {
for (Map<String, Object> item : list) {
if (id.equals(item.get("id"))) {
list.remove(item);
}
if (item.containsKey("children") && null != item.get("children")) {
List<Map<String, Object>> childrens = (List<Map<String, Object>>) item.get("children");
treeNode(id, childrens);
}
}
return list;
}
结果报错java.util.ConcurrentModificationException
报错信息中给出的错误位置在checkForComodification(), 查看此方法源码:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
代码修改
上面的代码在调用list.remove(item)
后会导致modCount != expectedModCount
,我们改为用iterator.remove()
可解决此问题。
private static List<Map<String, Object>> treeNode(Long id, List<Map<String, Object>> list) throws Exception {
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Map<String, Object> item = (Map<String, Object>) iterator.next();
if (id.equals(item.get("id"))) {
iterator.remove();
}
if (item.containsKey("children") && null != item.get("children")) {
List<Map<String, Object>> childrens = (List<Map<String, Object>>) item.get("children");
treeNode(id, childrens);
}
}
return list;
}
至于原因,大家看下ArrayList的内部类Itr源码,会发现在remove()方法里重新赋值了expectedModCount = modCount
private class Itr implements Iterator<E> {
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}