Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 遍历列表并允许它同时删除一个项(不是迭代器)_Java_Algorithm_List_Data Structures_Collections - Fatal编程技术网

Java 遍历列表并允许它同时删除一个项(不是迭代器)

Java 遍历列表并允许它同时删除一个项(不是迭代器),java,algorithm,list,data-structures,collections,Java,Algorithm,List,Data Structures,Collections,注意:我不知道doSomething是否会去除元素。这是我的数据结构需要处理的一个例外情况 我的问题很简单: int size = list.size(); for(int i = 0; i < size; i++) { MyObj mo = list.get(i); mo.doSomething(); } int size=list.size(); 对于(int i=0;i您可以使用阵列列表,例如,只要在删除某些内容时更新索引和大小 List<MyObj> li

注意:我不知道doSomething是否会去除元素。这是我的数据结构需要处理的一个例外情况

我的问题很简单:

int size = list.size();
for(int i = 0; i < size; i++) {
   MyObj mo = list.get(i);
   mo.doSomething();
}
int size=list.size();
对于(int i=0;i
现在如果doSomething()从列表中删除mo,我最终会得到ArrayIndexOutOfBounds,因为列表现在已经缩小了

我应该使用什么样的数据结构来允许有可能删除的迭代?我不能在这里使用迭代器,换句话说,我不能让doSomething返回布尔值并调用iterator.remove()。数据结构必须以某种方式处理这种情况,并继续迭代仍然存在的其余元素

编辑:我不知道doSomething是否会删除元素。这是我的数据结构需要处理的一个例外情况


第二部分=>

您可以使用
阵列列表
,例如,只要在删除某些内容时更新索引和大小

List<MyObj> list = new ArrayList<MyObj>();
int size = list.size();
for(int i = 0; i < size; i++) {
    MyObj mo = list.get(i);
    mo.doSomething();
    if (size > list.size()) {
        size = list.size();
        i--;
    }
}
List List=new ArrayList();
int size=list.size();
对于(int i=0;i列表.大小()){
size=list.size();
我--;
}
}
这仅在移除的项目是最后一个检查的项目时有效。对于列表的其他更改,您必须有更复杂的逻辑

我应该使用什么样的数据结构来允许有可能删除的迭代

最简单的选择是复制列表并迭代:

List copy=newarraylist(列表);
用于(MyObj mo:副本){
mo.doSomething();
}
现在,不管是否有任何东西从原始列表中删除了一个想法,这都不会改变列表的副本

另一个选择是使用。然后,您可以随意迭代、删除或添加项目:

“快照”样式的迭代器方法使用对创建迭代器时数组状态的引用。该数组在迭代器的生命周期内不会更改,因此不可能发生干扰,并且迭代器保证不会抛出ConcurrentModificationException。自创建迭代器以来,迭代器不会反映对列表的添加、删除或更改


我认为你应该改变你的
doSomething()
。如果
mo.doSomething()
可以从
l
中删除
mo
,则您必须知道自己的
l

您可以这样更改代码:

在MyObj内部创建一个有效的标志。只有在有效时才听

while(list.hasNext()) {
   MyObj mo = list.next()
   if(mo.isValid()){
       mo.doSomething();
   } else {
       list.remove();
   }
}

您知道
doSomething()
是否实际删除了
mo
?如果是这样的话,请稍后打电话给
--i
,你会没事的。@TomaszNurkiewicz这就是问题所在,Tomasz,我不知道,所以你的解决方案不起作用:(这不起作用,因为我不知道该元素是否将被删除。请参阅问题中的“我的编辑”。@chrisapotek:好的,更改为检查是否删除了某些内容。hummm。您确定只要删除的元素是当前正在迭代的元素,这就起作用吗?@chrisapotek:在该条件下,我确定,是的。@chrisapotek:当您删除一个对象时对象之后的索引被下移,因此您需要再次检查相同的索引。谢谢Jon,但是每次迭代之前复制都太昂贵了。我想@Keppil建议效果更好。@chrisapotek:请看我的编辑-
CopyOnWriteArrayList
可能更合适。我个人更喜欢这种只有在允许的更改是删除当前元素。感谢CopyOnWriteArrayList类的建议。它确实知道…mo将自己作为侦听器从列表中删除,然后出现问题…为什么您认为这听起来很奇怪?我知道您编写了“非迭代器”但我认为thwas是因为您将mo从列表中删除。这不起作用。我只知道在执行doSomething后mo是否有效…这将起作用,但在第一次迭代中不会起作用。您将在第二次迭代列表时从列表中删除mo。这将导致一个包含无效mo的列表。但您编写了performance很重要。如果列表中没有那么多项目,它可能会起作用。
while(list.hasNext()) {
   MyObj mo = list.next()
   if(mo.isValid()){
       mo.doSomething();
   } else {
       list.remove();
   }
}