Java-在浏览ArrayList时向其添加元素

Java-在浏览ArrayList时向其添加元素,java,Java,问题是我有一个方法createNode(),它在树中创建一个节点,然后如果它是一个离开节点,它会将它添加到ArrayList treeLeaves,我在浏览treeLeavesArrayList时调用这个方法,如下所示: Iterator<Tree> iter = treeLeaves.iterator(); while (iter.hasNext()) { iter.next().createNode(); } For (Tree

问题是我有一个方法
createNode()
,它在树中创建一个节点,然后如果它是一个离开节点,它会将它添加到
ArrayList treeLeaves
,我在浏览
treeLeaves
ArrayList时调用这个方法,如下所示:

    Iterator<Tree> iter = treeLeaves.iterator();
    while (iter.hasNext()) {
        iter.next().createNode();
    }
    For (Tree cursor : treeLeaves) {
        cursor.createNode();
    }
但我一直有一个例外:

    Exception in thread "main" java.util.ConcurrentModificationException
即使将下面的代码放入
snychronized(treeLeaves){}
bloc。
我不知道这是否有用,但是;这是一个n-树。

您需要一个ConcurrentList

阅读


此外,您在浏览arraylist时无法更改它。。。相反,如果您愿意,您可以使用tempoaray内存中的缓冲区编辑当前列表。

您需要一个ConcurrentList

阅读


此外,您在浏览arraylist时无法更改它。。。相反,如果愿意,您可以使用tempoaray内存中的缓冲区编辑当前列表。

这是因为在Java中,当创建迭代器时,您无法修改底层数据结构。增强的for循环“for(Tree cursor:treeLeaves))”使用迭代器


正如Ya所说,“在浏览arraylist时,您也不能更改它……相反,如果您愿意,您可以使用tempoaray内存中的缓冲区来编辑当前列表。”

这是因为在Java中,当创建迭代器时,您无法修改基础数据结构。增强的for循环“for(Tree cursor:treeLeaves))”使用迭代器


正如Ya所说,“在浏览arraylist时,您也不能更改它……相反,如果您愿意,您可以使用tempoaray内存中的缓冲区来编辑当前列表。”

简而言之,在大多数情况下,如果您更改集合的结构,所有仍然打开的迭代器都将无效。(相当多的例外,包括使用并发集合,或者通过迭代器进行修改,等等)

您的问题可以通过以下方式轻松演示:

List<Node> treeLeaves = new ArrayList<>();

//... add something to treeLeaves

for (leaf :  treeLeaves) {
    treeLeaves.add(new Node());
}
List treeLeaves=new ArrayList();
//... 在树视图中添加一些内容
用于(叶:树叶){
添加(新节点());
}
对于您的情况,可以通过创建一个新集合进行迭代来轻松解决:

List<Node> treeLeaves = new ArrayList<>();
//... add something to treeLeaves

List<Node> tempLeaves = new ArrayList<>(treeLeaves);    
for (leaf :  tempLeaves ) {
    treeLeaves.add(new Node());
}
List treeLeaves=new ArrayList();
//... 在树视图中添加一些内容
List tempLeaves=新的ArrayList(treeLeaves);
用于(叶:模板叶){
添加(新节点());
}

简而言之,在大多数情况下,如果更改集合的结构,所有仍然打开的迭代器都将无效。(相当多的例外,包括使用并发集合,或者通过迭代器进行修改,等等)

您的问题可以通过以下方式轻松演示:

List<Node> treeLeaves = new ArrayList<>();

//... add something to treeLeaves

for (leaf :  treeLeaves) {
    treeLeaves.add(new Node());
}
List treeLeaves=new ArrayList();
//... 在树视图中添加一些内容
用于(叶:树叶){
添加(新节点());
}
对于您的情况,可以通过创建一个新集合进行迭代来轻松解决:

List<Node> treeLeaves = new ArrayList<>();
//... add something to treeLeaves

List<Node> tempLeaves = new ArrayList<>(treeLeaves);    
for (leaf :  tempLeaves ) {
    treeLeaves.add(new Node());
}
List treeLeaves=new ArrayList();
//... 在树视图中添加一些内容
List tempLeaves=新的ArrayList(treeLeaves);
用于(叶:模板叶){
添加(新节点());
}

对于
ArrayList
,只需使用索引即可避免迭代器:

for (int i = 0; i < treeLeaves.size(); i++) {
    Tree current = treeLeaves.get(i);
    // your code
}
for(int i=0;i

只要你做的事情是追加到数组的末尾,你不插入中间或开始,或者删除任何项目,这将是有效的。code>treeLeaves.size()将在每次执行循环时重新计算,这意味着如果附加到末尾,将重新计算大小,并且

i
将进入新项。是的,使用旧式循环不像迭代器那样“酷”,但它可以工作


除了
ArrayList
之外,我不建议对任何类型的
List
使用它,因为一般来说,
get(I)
必须从列表的开头开始,逐步遍历每个元素(除非运行时优化了在
get(I)之后使用
get(I+1)
,这不会太难,但我不知道实现是否做到了这一点)。但是,对于
ArrayList
get(i)
应该花费恒定的时间

对于
ArrayList
,只需使用索引即可避免迭代器:

for (int i = 0; i < treeLeaves.size(); i++) {
    Tree current = treeLeaves.get(i);
    // your code
}
for(int i=0;i

只要你做的事情是追加到数组的末尾,你不插入中间或开始,或者删除任何项目,这将是有效的。code>treeLeaves.size()将在每次执行循环时重新计算,这意味着如果附加到末尾,将重新计算大小,并且

i
将进入新项。是的,使用旧式循环不像迭代器那样“酷”,但它可以工作


除了
ArrayList
之外,我不建议对任何类型的
List
使用它,因为一般来说,
get(I)
必须从列表的开头开始,逐步遍历每个元素(除非运行时优化了在
get(I)之后使用
get(I+1)
,这不会太难,但我不知道实现是否做到了这一点)。但是,对于
ArrayList
get(i)
应该花费恒定的时间

同步列表没有帮助
ConcurrentModificationException
意味着对集合的访问不仅仅是多线程的。好的,非常感谢@Ya Wang,我将尝试一下,我会接触到的。这确实很棒,我不再有例外。谢谢。发生的事情实际上与我的解决方案没有什么不同:P COW实际上意味着当你添加到列表中时,它有了一个列表的新副本(而你仍在迭代原始副本)。同步列表没有任何帮助
ConcurrentModificationException
意味着对集合的多线程访问。好的,非常感谢@Ya Wang