[英]Java: How to remove elements from a list while iterating over/adding to it
这个问题是在描述(和解决)问题的一个比较特殊的情况下这个问题 。
我有两个方法,stopAndRemove(ServerObject服务器)和close()方法。 后者应关闭所有服务器并将其从服务器列表中删除。 该列表定义为
List<ServerObject> server.
我不想在closeCurrentlyOpen中使用stopAndRemove中的几乎相同的代码,所以我想做类似的事情:
public void closeCurrentlyOpen() {
for(ServerObject server : this.servers) {
stopAndRemove(server)
}
}
这将不起作用,因为这将导致ConcurrentModificationException。 我试着复制一份清单
List<ServerObject> copyList = new ArrayList<ServerObject>(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循环中将它们全部停止并在结尾处清除列表)。
与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);
你应该得到一个迭代器并使用它删除。 您将获得异常,因为迭代器在java中是快速失败的 。
回答问题的标题,而不是给定示例的具体细节。 事实上,这种解决方案在特定情况下甚至不合适(重构是合适的,正如其他人所建议的那样)。
但是,似乎很多java程序员都不知道CopyOnWriteArrayList (JDK自1.5以来的一部分),并且正在尝试将自己的解决方案推向同一个问题(迭代前的复制列表)。
...从目录列表中删除非XML文件...
List<File> files = Arrays.asList(dir.listFiles());
Iterator<File> i = files.iterator();
while (i.hasNext()) {
File file = i.next();
if (!file.getName().endsWith(".xml")) {
i.remove();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.