如何通过java中的间接操作同时修改集合?

时间:2014-12-01 13:21:13

标签: java list iteration

我已经阅读了一些关于列表并发性的内容,并且我正面临这个问题:

我有一份我需要经历的清单。每次我处理此列表中的元素时,都会发生一些列表更改效果(在许多其他事情中)。

  • 当前元素可以被丢弃(并在列表中用空格替换以标记空白点)
  • 列表中的其他随机元素可以被丢弃(并替换为null)
  • 可以将元素添加到列表的末尾(可以是之前由其他操作删除的元素)

这些列表更改效果不会在循环期间直接发生。它们可以通过对其中一个元素的动作触发。所有这些都是同步完成的。

这是目前的简化版本。

class Container {
    List<Element> elements;

    // It starts here
    public void process() {
        for (Element el: this.elements)) {
            el.doSomething(this);
        }
    }

    public void removeElement(Element el) {
        this.elements.remove(el);
    }
}

class Element {
    public void doSomething(Container c) {
        this.doThis();
        this.getAction().applyTo(c);
    }
}

class MyAction implements Action<Container> {
    void applyTo(Container c) {
        for (Element el: this.getElements())) { // getElements does an immutable copy of this.elements
            el.doThat();
            if(el.shouldBeRemoved()) {
                c.removeElement(el);
            }
        }
    }
}

我找到的最佳解决方案如下:

public void process() {
    for (Element el: this.getElements()) {// getElements does an immutable copy of this.elements
        if (!this.elements.contains(el)) continue;
        el.doSomething(this);
    }
}

它没有说明一个元素可以添加到列表中的事实,但我目前不需要处理在process()调用期间添加的元素。

所以这样可行,但会导致很多列表复制。

我已经考虑过CopyOnWriteArrayList,但它仍然会复制列表,除非它可能会在循环过程中复制很多时间,但性能较差。 我已将ListIterator放在一边,因为我需要引用原始列表迭代器。

我想到的最后一个选项是标记元素而不是用null替换它们,这样它们就会被任何动作忽略,但这会迫使我添加很多条件,如:el.isFlagOk()。另外,它会强制我复制元素,以防需要将删除的元素添加回到最后(而不是像我现在那样重置它)。 仅供参考,该列表的最大功能大小为10。

是否存在支持这种交织行为的列表类型结构?

1 个答案:

答案 0 :(得分:0)

那么你需要的是元素可以在迭代列表时潜在地调整列表吗?

对于这个可能你可以看看容器中有2个列表。其中一个可以被迭代获得,一个被编辑。编辑后需要在迭代完成时替换迭代列表。

所以:

class Container {
    List<Element> elements;
    List<Element> itr;

    ...
    public void process() {
        for (Element el: itr) {

            el.doSomething(this);
        }
        swap();

    }

    private void swap(){
         itr = elements;
         elements = getElements();//assuming getElements does an immutable copy of this.itr
    }

}