LinkedList:删除一个对象

Xol*_*lve 15 java linked-list

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

for(ObjectType ob : obList) {
  if(ob.getId() == id) {
    obList.remove(ob);
    break;
   }
}
Run Code Online (Sandbox Code Playgroud)

pol*_*nts 16

其他人提到了有效点,通常这不是你如何remove从集合中的对象.但是,在这种情况下,break一旦你离开循环,它就没问题remove.

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

所以,是的,如果你break离开了foreach你之后remove,你会没事的.


对于那些说这会因为你无法修改集合而失败的人foreach- 只有你想继续迭代才会这样.这不是这种情况,所以这条捷径很好.

ConcurrentModificationException迭代器检查并抛出A. 在这之后remove(有资格作为并发修改),你就break离开了循环.迭代器甚至没有机会检测到它.

最好是添加注释break,为什么它是绝对必要的等等,因为如果稍后修改此代码以继续在a之后迭代remove,则它将失败.

我会把这个成语看作goto(或者更确切地说,标记为break/ continue):它起初可能看起来不对,但是当明智地使用它时,它会使代码更清晰.

  • 但是,当nexte开发人员试图添加一些功能而没有"看到"这个陷阱时,它很可能在未来的版本中失败.你应该清楚地记录下来. (3认同)
  • 如果这是一个链表,那么Iterator.remove()比List.remove(Object)更有效,因为后者必须重新搜索对象.我会使用Iterator,它原则上是删除. (3认同)

Law*_*Dol 7

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

  1. 例如,集合可以是链表(在你的情况下是),其删除方法意味着重新搜索对象,哪个搜索可能具有O(n)复杂度.
  2. 除非使用迭代器的remove方法,否则在删除后无法继续迭代.现在你要删除第一次出现 - 将来你可能需要删除所有匹配的事件,在这种情况下你必须重写循环.

原则上,我建议在增强版之前使用以下内容:

for(Iterator<ObjectType> it=obList.iterator(); it.hasNext(); ) {
    if(it.next().getId()==id) { 
        it.remove(); 
        break;
        }
    } 
Run Code Online (Sandbox Code Playgroud)

这样,您就不会对可能在未来发生变化的基础列表做出假设.


比较代码以删除迭代器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;
}
Run Code Online (Sandbox Code Playgroud)

反对删除(对象)必须做的事情:

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;
}
Run Code Online (Sandbox Code Playgroud)


JRL*_*JRL 6

你应该使用iterator.remove():

从底层集合中移除迭代器返回的最后一个元素(可选操作).每次调用next时,只能调用一次此方法.迭代器的行为是不确定如果底层的集合被修改,迭代是在比调用此方法之外的任何方式的进步.