[英]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.