我的适配器中有此代码,其中显示了学校列表。还有一个搜索过滤器。只要搜索过滤器有一个值,列表就必须显示包含搜索过滤器字母的学校。这是我的代码-
public boolean refreshAdapter() {
List<School> schools = cache().getSchools();
if (schoolList != null && !schoolList.isEmpty()) {
schoolList .clear();
}
schoolList = schools;
for (School school: schoolList) {
String name = school.getName();
String address = vehicle.getAddress();
if (name.contains(searchFilterText)|| address.contains(searchFilterText)) {
schoolList.add(school);
}
}
notifyDataSetChanged();
if (schoolList!= null) {
return schoolList.isEmpty();
}
return false;
}
如何在没有并发修改异常的情况下运行此代码?我尝试使用ListIterator,但没有帮助我
答案 0 :(得分:2)
ConcurrentModificationException
的产生是因为schoolList
列表在迭代该列表的过程中被修改。一种替代方法是改为迭代schools
列表,并对schoolList
进行添加,从而将要迭代的列表与要修改的列表分开:
schoolList = new ArrayList<>();
for (School school: schools) {
String name = school.getName();
String address = vehicle.getAddress();
if (name.contains(searchFilterText)|| address.contains(searchFilterText)) {
schoolList.add(school);
}
}
另一种替代方法(使用JDK 8或更高版本)是过滤schools
列表并将结果捕获到schoolList
中:
schoolList = schools.stream()
.filter(school -> school.getName().contains(searchFilterText) || school.getAddress().contains(searchFilterText))
.collect(Collectors.toList());
根据代码的当前状态,您似乎将重新添加元素到schoolList
,因为它已经包含了这些元素,因此为什么要遍历它们。上面的代码示例生成仅包含匹配元素的列表。如果希望将匹配元素重新添加到schoolList
中,如原始问题所示,则可以在第一个示例中替换以下行
schoolList = new ArrayList<>();
使用
schoolList = new ArrayList<>(school);
这将创建school
列表的副本,并将其存储在迭代开始之前的schoolList
中。
如果这是预期的行为,请小心,因为这可能会导致无限循环。例如,在原始问题中,如果未引发ConcurrentModificationException
,则如果添加与条件(School
)相匹配的name.contains(searchFilterText)|| address.contains(searchFilterText)
对象,则稍后也会对其进行迭代。反过来会匹配条件,然后重新添加。此过程将无限重复。例如,假设schoolList
中唯一的元素与条件匹配,则以下是每次迭代后schoolList
中包含的结果:
迭代0:
matching school A <-- Current element of iteration
matching school A <-- [newly added element]
迭代1:
matching school A
matching school A <-- Current element of iteration
matching school A <-- [newly added element]
迭代2:
matching school A
matching school A
matching school A <-- Current element of iteration
matching school A <-- [newly added element]
无限等等。
答案 1 :(得分:0)
您得到ConcurrentModificationException
-s的原因是您在遍历列表的同时向其添加内容。通常,这是禁止的,因为通过迭代添加内容会造成混淆。在某些情况下,程序员希望迭代迭代最近添加的项,有时则不需要。因此,java迫使我们明确地执行上述任一操作。
您可以使用存储要添加到列表中的项目的临时列表进行修复。
List<School> tempSchoolList = new ArrayList<>(); // this is the new list
// most of the things below comes from the original code
schoolList = schools;
for (School school: schoolList) {
String name = school.getName();
String address = vehicle.getAddress();
if (name.contains(searchFilterText)|| address.contains(searchFilterText)) {
tempSchoolList.add(school); // add the new list to the temp school list
}
}
schoolList.addAll(tempSchoolList);
答案 2 :(得分:0)
请注意,发生此异常的原因是您在迭代集合时不得向集合中添加元素。您是否对schools
和shoolList
感到困惑?为他们提供更合理的名称会很有帮助!
要正确执行此操作,您必须构建一个新的过滤列表(我评论了更改的行)
// this is the new filtered list
schoolList = new ArrayList<>();
// iterate the original list
for (School school: schools) {
String name = school.getName();
String address = vehicle.getAddress();
if (name.contains(searchFilterText)|| address.contains(searchFilterText)) {
// add it to filtered list
schoolList.add(school);
}
}