这是使用for循环从Java中的LinkedList查找和删除项目的有效方法,是否可能出现不一致:
for(ObjectType ob : obList) {
if(ob.getId() == id) {
obList.remove(ob);
break;
}
}
答案 0 :(得分:16)
其他人已经提到了有效点,通常这不是你remove
来自集合的对象的方式。但是,在这种情况下,一旦break
remove
remove
离开循环就没问题了。
但是,如果要在ConcurrentModificationException
之后继续迭代,则需要使用迭代器。否则,您将获得break
,或者更常见的情况是未定义的行为。
是的,如果foreach
remove
foreach
之后ConcurrentModificationException
,那么>} 。
对于那些说这会因为你无法修改remove
中的集合而失败的人 - 只有当你想继续迭代时才会这样。这不是这种情况,所以这条捷径很好。
迭代器检查并抛出break
。在break
(有资格作为并发修改)之后,您remove
退出循环。迭代器甚至没有机会检测到它。
最好是在goto
添加评论,为什么绝对必要等等,因为如果稍后修改此代码以继续在break
之后进行迭代,它将会失败强>
我会将这个习惯用法视为continue
(或者更确切地说,标记为{{1}} / {{1}}):起初看起来似乎有些错误,但如果明智地使用,它会让人更清洁代码。
答案 1 :(得分:7)
最好使用迭代器,并在搜索对象时通过遍历集合来删除它来使用它的remove方法。这是因为
我建议,原则上,改为使用以下内容并使用此类内容:
for(Iterator<ObjectType> it=obList.iterator(); it.hasNext(); ) {
if(it.next().getId()==id) {
it.remove();
break;
}
}
通过这种方式,您不会对未来可能发生变化的基础列表做出假设。
比较代码以删除迭代器remove(格式化Sun)调用的最后一个条目:
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}
针对remove(Object)必须执行的操作:
public boolean remove(Object o) {
if (o==null) {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
remove(e);
return true;
}
}
} else {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}
答案 2 :(得分:6)
您应该使用iterator.remove()
:
从基础集合中删除 最后一个元素返回 迭代器(可选操作)。这个 方法只能调用一次 打电话到下一个。一个人的行为 迭代器是未指定如果是 底层集合已修改 而迭代正在进行中 通过调用此方式以外的任何方式 方法
答案 3 :(得分:4)
编辑:事实上,由于休息,它不会失败。有关详细信息,请参阅polygenelubricant的答案。
然而,这是危险的方法。要在Java中同时迭代和修改集合,必须使用“ListIterator”对象,并使用迭代器自己的“add()”和“remove()”方法,而不要使用集合中的方法。
您可以在java doc中查看“java.util.Iterator”和“java.util.ListIterator”类
答案 4 :(得分:1)
尝试这样的事情:
Iterator<ObjectType> iter = obList.iterator();
while (iter.hasNext()) {
ObjectType ob = iter.next();
if(ob.getId() == id) {
iter.remove();
break;
}
}
这是Iterator不能被foreach循环取代的最后一个地方。
答案 5 :(得分:1)
要避免ConcurrentModifiationException ,您可以这样做:
final Iterator<ObjectType> i = obList.iterator();
while (i.hasNext()) {
if (i.next().getId() == id) {
i.remove();
}
}
或
for (int i = 0; i < obList.size(); i++) {
if (obList[i].getId() == id) {
obList.remove(i);
}
}
我更喜欢第一个。处理索引更加错误,并且可以有效地实现迭代器。第一个建议适用于Iterable,而第二个建议适用于List。
答案 6 :(得分:0)
CopyOnWriteArrayList
可能是您正在寻找的。执行变异操作时,会生成基础数组的副本。这允许在for-each循环内修改列表元素。请记住,这不是一个链表,可能效率很低。
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class Main {
public static void main(String[] args) {
List<String> myList = new CopyOnWriteArrayList<String>();
myList.add("a");
myList.add("b");
myList.add("c");
// Will print [a, b, c]
System.out.println(myList);
for (String element : myList) {
if (element.equals("a")) {
myList.remove(element);
}
}
// Will print [b, c]
System.out.println(myList);
}
}
答案 7 :(得分:0)
上面的第二个循环应该稍微改变
for (int i = 0; i < obList.size(); ) {
if (obList.get(i).getId() == id) {
obList.remove(i);
continue
}
++i;
}
或
for (int i = obList.size() - 1; i >= 0; --i) {
if (obList.get(i).getId() == id) {
obList.remove(i);
}
}