我正试图编写一个程序,如果名称具有特定值,该程序将从ArrayList
中删除名称,但我无法做到这一点。
class UserNamesTest {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("John");
names.add("Jerry");
names.add("Jim");
names.add("Todd");
for(String name : names) {
if(name.equals("John")) {
System.out.println("true");
names.remove(names.indexOf(name));
}
}
}
}
当我执行这个代码时,我得到一个异常:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at UserNamesTest.main(UserNamesTest.java:13)
我怎样才能做到这一点?
使用迭代器不对正在迭代的List
进行操作:
Iterator<String> iterator = names.iterator();
while(iterator.hasNext()) {
String name iterator.next();
if(name.equals("John")) {
System.out.println("true");
iterator.remove();
}
}
除了使用Iterator
,使用java-8,您还可以执行以下操作,
names = names.stream()
.collect(Collectors.partitioningBy(e->e.equals("John")))
.get(false);
或更可读的过滤器,
names = names.stream()
.filter(e->e.equals("John"))
.collect(Collectors.toList());
使用Java8或11可以:
class UserNamesTest {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("John");
names.add("Jerry");
names.add("Jim");
names.add("Todd");
List<String> namesWithoutJohn = names.stream()
.filter(((Predicate<String>)("John"::equals)).negate()) // Java 8
// .filter(Predicate.not("John"::equals)) // Java 11
.collect(Collectors.toList());
}
}
因为当java文档不允许对对象进行并发修改时,检测到对象并发修改的方法可能会引发此异常。在列表中使用removeIf
。
ArrayList<String> names = new ArrayList<>();
names.add("John");
names.add("Jerry");
names.add("Jim");
names.add("Todd");
names.removeIf(name->name.equals("John"));
或者只需使用Iterator
Iterator<String> iter = names.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (str.equals("John"))
iter.remove();
}
请注意,Iterator.remove()
是在迭代过程中修改集合的唯一安全方法。有关迭代器的更多信息
使用索引遍历列表以删除项时要小心。因为项目在移动后会发生移动,所以您可能会错过其中的一些项目。这里有一个例子:
ArrayList<String> names = new ArrayList<>();
names.add("Jerry");
names.add("Jim");
names.add("John");
names.add("John");
names.add("Todd");
for(int i = 0; i < names.size(); i++) {
String name = names.get(i);
if(name.equals("John")) {
names.remove(i);
}
}
names.forEach(System.out::println);
打印
Jerry
Jim
John <-- wasn't removed
Todd
如果你打算这样做,从最后一个项目开始,因为删除一个项目不会影响后续的位置。
names = new ArrayList<>();
names.add("Jerry");
names.add("Jim");
names.add("John");
names.add("John");
names.add("Todd");
for (int i = names.size() -1; i >= 0; i--) {
String name = names.get(i);
if(name.equals("John")) {
names.remove(i);
}
}
names.forEach(System.out::println);
打印
Jerry
Jim
Todd
但我更喜欢使用以下方法:
names.removeIf(name->name.equals("John"));
它只需一句话就能让所有人都明白。