【类型定位】
java.util.ConcurrentModificationException这种类型的crash我们在使用容器的迭代器的时候可能会遇到,它对应了迭代器失效这一类型的crash。这种crash的成因是在遍历容器的过程中,动态更改了容器中的内容大小(增加或者删除),这样引起了迭代器失效的问题。
【解决方案】
迭代器失效的问题,解决的方案比较简单:先拷贝一份临时容器存放原来容器中的内容,再对这份临时的容器进行遍历操作,这样即使在遍历操作过程中会有对容器内容有增删的操作,也可以将这部分增删操作作用于原来的容器,而不影响现在正在遍历的容器。
【代码展示】
首先是会引起java.util.ConcurrentModificationException的crash:
public class MainActivity extends AppCompatActivity {
List<String> datas = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 10; ++i) {
datas.add(i, "item" + i);
}
for (String str : datas) {
removeOneDataItem(str);
//addOneDataItem(str);
}
}
void removeOneDataItem(String str) {
datas.remove(str);
}
void addOneDataItem(String str) {
datas.add(datas.size(), str);
}
}
下面同时定义临时容器存放原来容器中的对象,遍历新的临时容器,再操作原来的容器:
public class MainActivity extends AppCompatActivity {
List<String> datas = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 10; ++i) {
datas.add(i, "item" + i);
}
/**
* 关键是这一步:将原来需要遍历的容器拷贝一份临时
* 后续遍历操作在这份容器中
* 增删操作在原来的容器中
*/
List<String> tempDatas = new ArrayList<>(datas);
for (String str : tempDatas) {
removeOneDataItem(str);
//addOneDataItem(str);
}
}
void removeOneDataItem(String str) {
datas.remove(str);
}
void addOneDataItem(String str) {
datas.add(datas.size(), str);
}
}
【个人总结】
- java.util.ConcurrentModificationException 对应着迭代器失效的问题
- 迭代器失效问题,可以预先存一份临时容器,遍历这份临时容器,操作则在原来的容器中