簡體   English   中英

Java:如何在迭代/添加元素時從列表中刪除元素

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM