如果大小写匹配,则从ArrayList中删除名称无效



我正试图编写一个程序,如果名称具有特定值,该程序将从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"));

它只需一句话就能让所有人都明白。

最新更新