[英]Remove List Item without Iterator.remove() in Java
我有一個基本的事件管理器設置,該設置可循環訪問偵聽器的鏈接列表以將事件通知他們。 偵聽器都是通過層次結構關聯的(一個控制另一個),在一個特定事件期間,一個對象將從列表中刪除另一個。 刪除的對象位於層次結構的底部,沒有自己的子級。
因此,我目前正在獲取ConcurrentModificationException,並且由於我要刪除的對象不是當前迭代的對象,因此無法使用iterator和iterator.remove()。
有什么干凈的方法可以刪除此對象? 我想避免對子對象進行重組以使其可重用,因為這會破壞我的許多測試套件,但是我寧願擁有高質量的代碼。 我在此項目上使用Java 7,無法升級到Java 8。
下面是示例代碼,以及我想出的唯一想法。 該代碼並不精確,僅用於說明我當前設置的結構。
活動管理器通知:
public void notifyListeners(Object sender, EventArgs args) {
for (Listener l : listeners) {
l.notify(sender, args);
}
}
偵聽器示例:
public class Listener {
...
private Listener myChild;
public void notify(Object sender, EventArgs args) {
if (myChild != null) {
eventManager.removeListener(myChild);
}
mychild = new Child();
eventManager.addListener(myChild);
}
...
}
我的想法(未經測試):
public void notifyListeners(Object sender, EventArgs args) {
int listSize = listeners.size();
for (int i = 0; i < listSize; i++) {
l.notify(sender, args);
if (listeners.size() != listSize) {
listSize = listeners.size();
i = listeners.indexOf(l);
}
}
}
work for now, this could easily break in the future. 雖然我的想法目前行得通,但將來很可能會打破。 而且它也不安全。
謝謝您的幫助。
您可以在開始遍歷偵聽器以處理事件時復制偵聽器的集合。 例如:
for(Listener l : new ArrayList<Listener>(listeners)) {
您將不得不復制列表,但這樣for循環將在與您以后修改的偵聽器不同的偵聽器集合上工作。
不行 Javadoc的Iterator.remove()
(部分),
如果在迭代進行過程中以其他方式(而不是通過調用此方法)修改了基礎集合,則未指定迭代器的行為。
您可以利用CopyOnWriteArrayList,檢查以下代碼。
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
public class Test{
List<String> stringList = new CopyOnWriteArrayList<String>();
public void test(){
for(int i=0;i<100;i++){
stringList.add("item"+i);
}
new IteratorThread().start();
new RemoveThenAddThread().start();
}
class IteratorThread extends Thread{
public void run(){
while(true) {
for (String l : stringList) {
System.out.println(l);
//DO SOMETHING
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class RemoveThenAddThread extends Thread{
public void run(){
while(true) {
stringList.remove(0);
stringList.add("string item");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args)
{
new Test().test();
}
}
我看了Frank Zheng提到的CopyOnWriteArrayList,看看這是否是我真正想要的。 雖然不是,但這確實使我找到了ConcurrentLinkedQueue,它可以完美地處理我的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.