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