Java:如何在迭代/添加元素时从列表中删除元素

这个问题是这个问题中描述(和解决)问题的一个更特殊的例子。

我有两个方法,stopAndRemove(ServerObject服务器)和close()方法。 后者应关闭所有服务器并将其从服务器列表中删除。 该列表定义为

List server. 

我不想在closeCurrentlyOpen中使用stopAndRemove中的几乎相同的代码,所以我想做类似的事情:

 public void closeCurrentlyOpen() { for(ServerObject server : this.servers) { stopAndRemove(server) } } 

这将不起作用,因为这将导致ConcurrentModificationException。 我试着复制一份清单

 List copyList = new ArrayList(this.servers); 

并将其用作foreach循环的列表。 但是,当我在copyList上迭代时,另一个线程可能会将服务器附加到服务器列表,但closeCurrentlyOpen应该会产生一个emtpy列表。 当addServerToList方法同步到servers-list时,执行此操作

 public void closeCurrentlyOpen() { synchronized(this.servers) { for(ServerObject server : this.servers) { stopAndRemove(server) } } } 

将通过修改解决问题。 但是后来我无法在stopAndRemove方法中同步代码,如果直接调用它是必需的。

在我看来,这三种方法的设计可能需要修改。 任何人的想法?

从stopAndRemove()中分离出方法stop()。 然后使用显式迭代器编写循环,执行stop,然后使用iterator.remove()。

方法名称中的“和”是代码气味。

也许这是错误的方法,但我总是创建一个删除集合,其中包含对需要删除的对象的索引或引用。 然后我遍历该集合并从原始集合中删除这些索引/对象。 可能不是效率最高但它完成了工作。

代替

 for(Collection things : thing) things.remove(thing) 

我用

 Collection toRemove = new LinkedList(); for(things : thing) toRemove.add(thing); for(toRemove : thing) things.remove(thing) 

当我之前完成此操作时,我总是使用“旧学校”LinkedList集合,Iterator和Iterator.remove()方法来删除当前项目。

您可能会发现有关ConcurrentModificationException的这篇文章在此领域有一些建议。

将所有ServerObject停止代码从stopAndRemove重构为私有stopServer方法,然后在stopAndRemove和closeCurrentlyOpen中单独执行删除操作。 然后你可以使用ListIterator来删除它们(或者只是在for循环中将它们全部停止并在结尾处清除列表)。

回答问题的标题,而不是给定示例的具体细节。 实际上,这种解决方案在给定情况下甚至不合适(重构是合适的,正如其他人所建议的那样)。

但是,似乎很多java程序员都不知道CopyOnWriteArrayList (自1.5以来的JDK的一部分),并且正在尝试将自己的解决方案推向同一个问题(迭代前的副本列表)。

…从目录列表中删除非XML文件…

 List files = Arrays.asList(dir.listFiles()); Iterator i = files.iterator(); while (i.hasNext()) { File file = i.next(); if (!file.getName().endsWith(".xml")) { i.remove(); } } 

与firebird84相似。 但你可以使用removeAll(Collection c)api

 for(String exitingPermission : existingPermissions){ //remove all permissions for the screen and add the new ones if(exitingPermission.split("_")[0].equals(screen)){ removePermissions.add(exitingPermission); } } existingPermissions.removeAll(removePermissions); 

你应该得到一个迭代器并使用它删除。 您将获得exception,因为迭代器在java中是快速失败的 。