Java 删除ArrayList对象问题

Java 删除ArrayList对象问题,java,Java,我在处理分配时遇到了从ArrayList中删除对象的问题 如果我使用“normal”for循环,它的工作原理如下 public void returnBook(String isbn){ for (int i = 0; i < booksBorrowed.size(); i++){ if (booksBorrowed.get(i).getISBN() == isbn){ booksBorrowed.ge

我在处理分配时遇到了从ArrayList中删除对象的问题 如果我使用“normal”for循环,它的工作原理如下

public void returnBook(String isbn){        
    for (int i = 0; i < booksBorrowed.size(); i++){            
        if (booksBorrowed.get(i).getISBN() == isbn){
            booksBorrowed.get(i).returnBook();
            booksBorrowed.remove(i);                
        }
    }
}

希望你们能让我轻松起来。

你们真的不应该这样做,因为他们最终会造成问题。相反,使用ArrayList的迭代器帮助您遍历列表,然后仅使用迭代器删除。这将有助于防止有害的并发修改错误。

在Java中使用增强的for循环时,它使用列表的迭代器对列表进行迭代。使用列表的remove函数删除项时,这将干扰迭代器的状态,迭代器将抛出ConcurrentModificationException。
使用简单for循环,您不会遇到这样的问题,因为您只使用列表,并且状态更改只发生在列表本身中

您的代码中有一个bug:

for (int i = 0; i < booksBorrowed.size(); i++){            
    if (booksBorrowed.get(i).getISBN() == isbn){
        booksBorrowed.get(i).returnBook();
        booksBorrowed.remove(i);                
    }
}
但这不是最好的方法,因为它的复杂性是O(n^2)

更好的方法是将所有保留项添加到另一个集合中,然后使用截断大小将它们复制回原始列表。它的复杂性是O(n)。当然,只有当有许多元素需要删除时,这才是一个问题

另外,在for-each构造中删除会破坏迭代器,因此在这种情况下,它不是处理列表的有效方法

但您可以执行以下操作:

    for (Iterator<String> i = a.iterator(); i.hasNext();) {
        Book next = i.next();
        if (book.getISBN() == isbn){
           book.returnBook();
           i.remove(i);                
        }
    }
for(迭代器i=a.Iterator();i.hasNext();){
下一本书;
if(book.getISBN()==isbn){
returnBook();
i、 删除(i);
}
}

同样,在这种情况下,复杂性是O(n^2)。

所有答案都很好。但我建议你重新考虑一下。我的意思是,你真的需要一个ArrayList还是一个HashMap更好?如果您的对象列表有一个unic键(ISBN),并且您使用它来获取每个对象,为什么不使用一个适合您的问题的集合呢

你只会这么做

public void returnBook(String isbn){        
     Book book = (Book) booksBorrowed.remove(isbn);            
     book.returnBook();    
}

您可以选择以下方法来避免ConcurrentModificationException:

List<Book> books = new ArrayList<Book>();
books.add(new Book(new ISBN("0-201-63361-2")));
books.add(new Book(new ISBN("0-201-63361-3")));
books.add(new Book(new ISBN("0-201-63361-4")));
或者您可以使用第三方库,如,它可以在幕后为您完成所有工作>

List<Book> filtered = select(books, 
                having(on(Book.class).getIsbn(), 
                        is(new ISBN("0-201-63361-2"))));
List filtered=选择(书籍、,
具有(在(Book.class.getIsbn()上),
is(新ISBN(“0-201-63361-2”);

如果您的问题是“为什么我会出错”,那是因为您无法从正在迭代的列表中删除项目。如果同一个ISBN可以在列表中出现两次,那么您的第一个循环中可能有一个bug。/golfclap使用“有害”注意来启发我如何使用迭代器删除Book Objective。这实际上取决于您的应用程序是什么,以及您想要什么样的性能。hashmap和arraylist迭代器的组合可以做到这一点。如果他在if语句的底部添加uber gross“i--;”,则第一个循环可以工作。在最后一个循环中,它是从arraylist中删除还是仅从迭代器中删除?不确定第一个循环是O(n^2)。找到移除所有ISBN的时间似乎是O(n)。移除单个元素对于ArrayList来说是O(n)-因为整个数组必须移位。有O(n)个移除操作。你救了我的命。谢谢
List<Book> books = new ArrayList<Book>();
books.add(new Book(new ISBN("0-201-63361-2")));
books.add(new Book(new ISBN("0-201-63361-3")));
books.add(new Book(new ISBN("0-201-63361-4")));
ISBN isbn = new ISBN("0-201-63361-2");
List<Book> found = new ArrayList<Book>();
for(Book book : books){
    if(book.getIsbn().equals(isbn)){
        found.add(book);
    }
}
books.removeAll(found);
ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
    if(iter.next().getIsbn().equals(isbn)){
        iter.remove();
    }
}
List<Book> filtered = select(books, 
                having(on(Book.class).getIsbn(), 
                        is(new ISBN("0-201-63361-2"))));