Java LinkedList:删除对象
这是使用for-each循环从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(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);
}
}