简体   繁体   English

[Java]在while循环中排队,无法修改值?

[英][Java]Queue in while loop, cannot modify the value?

This is my code: 这是我的代码:

Iterator it = queue.iterator();

while(it.hasNext()){
   random = randNumber(1,2);
        if(random == 1){
            queue.poll();
        } else {
            queue.add("new");
            queue.poll();
        }
}

It gives me: 它给了我:

Exception in thread "test" java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
    at java.util.LinkedList$ListItr.next(LinkedList.java:696)

Edit @Jon Skeet: 编辑@Jon Skeet:

What I want to do is: 我想做的是:

  • I have a queue list in, let say the size is 10, lets say: a,b,c,d ... j 我有一个队列列表,可以说大小为10,可以说:a,b,c,d ... j
  • Generate a number between 1 and 2. if 1, pull (remove the top element) else if 2 add new element 生成一个介于1和2之间的数字。如果为1,则拉(删除顶部元素),否则为2,则添加新元素
  • I will stop the loop until I added 3 new elements 在添加3个新元素之前,我将停止循环

In general, you can't modify collections while you're iterating over them. 通常,在迭代集合时不能修改它们。 One alternative is to build a separate list of "changes" you want to apply, and then apply them once you've finished iterating. 一种替代方法是构建要应用的“更改”的单独列表,然后在完成迭代后再应用它们。

Alternatively, some collections do support this such as ConcurrentLinkedQueue - but most offer no guarantees about whether the iterator will see the changes made while you're iterating. 另外,某些集合确实支持此功能,例如ConcurrentLinkedQueue但是大多数集合不能保证在迭代过程中迭代器是否会看到所做的更改。 (I suspect that's mainly because they're also thread-safe, but I've rarely seen documented guarantees about what will happen if you modify the collection within the iterating thread.) (我怀疑这主要是因为它们也是线程安全的,但我很少看到有文件记录的保证,如果您在迭代线程中修改集合会发生什么。)

EDIT: I'm not sure that an iterator is the right approach here. 编辑:我不确定在这里迭代器是正确的方法。 Instead, you could use: 相反,您可以使用:

while (!queue.isEmpty())
{
    // Put logic in here - add, poll etc
}

One thing to note is that your posted code doesn't actually move the iterator forward at any time - it never calls it.next() . 需要注意的一件事是,您发布的代码实际上不会在任何时候向前推动迭代器-它永远不会调用它it.next() That's a strong suggestion that either you're not using the iterator fully, or you don't need it at all. 强烈建议您没有完全使用迭代器,或者根本不需要迭代器。

Is this really copy-pasted your code? 这真的是复制粘贴的代码吗?

What I can think is that 我能想到的是 You confirmed that q and queue are references to the same queue-object. 您确认qqueue是对同一队列对象的引用。
So you cannot modify any type of list, queue, stack when iterating over it. 因此,在对其进行迭代时,您无法修改任何类型的列表,队列,堆栈。 To avoid iteration, you can try a for(int i = 0; ..... ; i++) loop. 为避免迭代,可以尝试for(int i = 0; ..... ; i++)循环。 But this isn't a good idea. 但这不是一个好主意。 Because you are changing size when you are using the size to check if you are at the end of the loop. 因为在使用尺寸检查循环是否结束时正在更改尺寸。


I read your edit: 我阅读了您的修改:

for (int i = 0; i < 3;)
{
    boolean b = Math.random() < 0.5d;
    if (b)
    {
         queue.poll();
    } else {
         queue.add("new"); // or put(), I don't know exectly
         i++;  
    }
}

If 'queue' is a List, you can use ListIterator 如果“队列”是列表,则可以使用ListIterator

excerpt: 摘抄:

An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration , and obtain the iterator's current position in the list. 列表迭代器,允许程序员在任一方向上遍历列表, 在迭代过程中修改列表 ,并获取迭代器在列表中的当前位置。

You should use ListIterator. 您应该使用ListIterator。 It has .remove() and .set() methods that will allow you to modify the underlying collection without hosing the iterator's state. 它具有.remove()和.set()方法,使您无需修改​​迭代器的状态即可修改基础集合。

In general, modifying the collection in any other way is going to hose the iterator's state--be glad it threw an exception and didn't do something more insidious. 总的来说,以任何其他方式修改集合都会削弱迭代器的状态-很高兴它抛出了异常并且没有做任何更隐蔽的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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