繁体   English   中英

在Java中删除没有Iterator.remove()的列表项

[英]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循环将在与您以后修改的侦听器不同的侦听器集合上工作。

不行 JavadocIterator.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM