Java LinkedList:删除对象

Java LinkedList:删除对象,java,linked-list,Java,Linked List,这是使用for-each循环从Java中的LinkedList查找和删除项的有效方法吗?是否可能出现不一致: for(ObjectType ob : obList) { if(ob.getId() == id) { obList.remove(ob); break; } } 编辑:事实上,它不会因为中断而失败。有关详细信息,请参见Polygene的答案 然而,这是一种危险的做法。要在Java中同时迭代和修改集合,必须使用“ListIterator”对象,并使用迭代器自

这是使用for-each循环从Java中的LinkedList查找和删除项的有效方法吗?是否可能出现不一致:

for(ObjectType ob : obList) {
  if(ob.getId() == id) {
    obList.remove(ob);
    break;
   }
}

编辑:事实上,它不会因为中断而失败。有关详细信息,请参见Polygene的答案

然而,这是一种危险的做法。要在Java中同时迭代和修改集合,必须使用“ListIterator”对象,并使用迭代器自己的“add()”和“remove()”方法,而不要使用集合上的方法


您可以在java文档中查看“java.util.Iterator”和“java.util.ListIterator”类

其他人提到了一个有效点,即通常情况下,这不是从集合中删除对象的方式。但是,在这种情况下,只要
删除
,就可以将
从循环中断开

但是,如果要在
删除后继续迭代,则需要使用迭代器。否则,您将得到一个
ConcurrentModificationException
,或者在更一般的情况下,是一个未定义的行为

所以,是的,如果在
删除
foreach
中中断
,您会没事的


对于那些认为这将失败,因为您无法在
foreach
中修改集合的人,只有在您希望继续迭代时,这才是正确的。这里不是这样,所以这条捷径很好

迭代器将检查并抛出一个
ConcurrentModificationException
。在这里,在
删除
(这符合并发修改的条件)之后,您将
从循环中中断。迭代器甚至没有机会检测到它

最好在
中断
上添加一条注释,说明为什么它是绝对必要的,等等,因为如果以后修改此代码以在
删除
后继续迭代,它将失败


我会把这个习惯用法与“转到”类似(或者更确切地说,标记为“断开”
/
继续”):一开始它可能看起来是错误的,但如果使用得当,它会使代码更干净。

尝试以下方法:

Iterator<ObjectType> iter = obList.iterator();
while (iter.hasNext()) {
  ObjectType ob = iter.next();
  if(ob.getId() == id) {
    iter.remove();
    break;
  }
}
Iterator iter=obList.Iterator();
while(iter.hasNext()){
ObjectType ob=iter.next();
if(ob.getId()==id){
iter.remove();
打破
}
}
这是foreach循环无法替代迭代器的最后几个地方之一。

a可能就是您要寻找的。执行变异操作时,将生成基础数组的副本。这允许在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);
    }

}
import java.util.List;
导入java.util.concurrent.CopyOnWriteArrayList;
公共班机{
公共静态void main(字符串[]args){
List myList=new CopyOnWriteArrayList();
myList.添加(“a”);
myList.添加(“b”);
myList.添加(“c”);
//将打印[a、b、c]
System.out.println(myList);
for(字符串元素:myList){
if(元素等于(“a”)){
myList.remove(元素);
}
}
//将打印[b,c]
System.out.println(myList);
}
}
您应该使用:

从基础集合中删除 返回的最后一个元素 迭代器(可选操作)。这 方法每次只能调用一次 打电话到下一个。一个人的行为 迭代器未指定,如果 基础集合已修改
当迭代在中进行时 除了打这个电话以外,还有别的办法吗 方法

要避免ConcurrentModificationException,可以执行以下操作:

final Iterator<ObjectType> i = obList.iterator();
while (i.hasNext()) {
    if (i.next().getId() == id) {
        i.remove();
    }
}
final迭代器i=obList.Iterator();
while(i.hasNext()){
if(i.next().getId()==id){
i、 删除();
}
}

for(int i=0;i

我更喜欢第一个。处理索引更容易出错,迭代器可以有效地实现。第一个建议适用于Iterable,而第二个建议需要一个列表。

最好使用迭代器并使用它的remove方法,通过迭代集合来搜索对象以删除它。这是因为

  • 例如,集合可以是一个链表(在您的例子中就是这样),其移除方法意味着再次搜索对象,搜索可能具有O(n)复杂度
  • 除非使用迭代器的remove方法,否则无法在删除之后继续迭代。现在您正在删除第一个引用-将来可能需要删除所有匹配的引用,在这种情况下,您必须重写循环
  • 原则上,我建议您放弃增强型,改为使用以下内容:

    for(Iterator<ObjectType> it=obList.iterator(); it.hasNext(); ) {
        if(it.next().getId()==id) { 
            it.remove(); 
            break;
            }
        } 
    
    for(Iterator it=obList.Iterator();it.hasNext();){ 如果(it.next().getId()==id){ it.remove(); 打破 } }
    这样,您就不会对未来可能发生变化的基础列表进行假设


    比较代码以删除迭代器remove(格式化Sun)调用的最后一个条目:

    private删除(条目E){
    if(e==标题)
    抛出新的NoTouchElementException();
    E结果=E元素;
    e、 previous.next=e.next;
    e、 next.previous=e.previous;
    e、 next=e.previous=null;
    e、 元素=空;
    大小--;
    modCount++;
    返回结果;
    }
    
    针对移除(对象)必须执行的操作:

    公共布尔删除(对象o){
    如果(o==null){
    for(条目e=header.next;e!=header;e=e.next){
    if(e.element==null){
    删除(e);
    返回true;
    }
    }
    }否则{
    for(条目e=header.next;e!=header;e=e.next){
    如果(o等于(e元素)){
    删除(e);
    复述
    
    for(Iterator<ObjectType> it=obList.iterator(); it.hasNext(); ) {
        if(it.next().getId()==id) { 
            it.remove(); 
            break;
            }
        } 
    
    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;
    }
    
    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;
    }
    
    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);
        }
    }