删除ArrayList对象问题
我有一个问题与删除从ArrayList中的赋值 工作时,如果我使用了“正常”的for循环的对象,它的工作原理如下删除ArrayList对象问题
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);
}
}
}
然而,当我试图简化代码具有增强的for循环,不工作,并显示java.util.ConcurrentModificationException错误:
public void returnBook(String isbn){
for (Book book: booksBorrowed){
if (book.getISBN() == isbn){
book.returnBook();
booksBorrowed.remove(book);
}
}
}
希望你们能减轻我..
你的替代方案,以避免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")));
收集所有要删除增强的for循环的记录,并在完成后遍历,您将删除所有找到的记录。
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
,它在迭代过程中支持remove方法。
ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
if(iter.next().getIsbn().equals(isbn)){
iter.remove();
}
}
或者你可以使用第三方库像LambdaJ,这让所有的工作,你在幕后>
List<Book> filtered = select(books,
having(on(Book.class).getIsbn(),
is(new ISBN("0-201-63361-2"))));
感谢队友,问题解决了:) – babygau 2012-04-01 04:05:12
你救了我的命。谢谢 – 2017-11-20 11:23:00
你真的不应该这样做,因为他们最终会造成问题。而是使用ArrayList的迭代器来帮助您遍历列表,然后仅使用迭代器进行删除。这将有助于防止有害的并发修改错误。
/golfclap使用'恶性' – 2012-04-01 03:28:44
你在你的代码中的错误:
for (int i = 0; i < booksBorrowed.size(); i++){
if (booksBorrowed.get(i).getISBN() == isbn){
booksBorrowed.get(i).returnBook();
booksBorrowed.remove(i);
}
}
它跳过删除那些后下一个元素。例如。当你删除'0th'元素时,1st变成0,但是这个代码不会遍历它。
这是一个正确的版本:
for (int i = booksBorrowed.size() - 1; i >= 0; i--){
if (booksBorrowed.get(i).getISBN() == isbn){
booksBorrowed.get(i).returnBook();
booksBorrowed.remove(i);
}
}
但是,这是不是最好的方法,因为它的复杂度为O(n^2)。
更好的方法是将所有保留的项目添加到另一个集合,然后将它们复制回带有截断大小的原始列表。它的复杂性是O(n)。当然,只有在有很多要删除的元素时才会担心。
P.S.在for-each构造中删除会破坏迭代器,所以在这种情况下处理列表不是一种有效的方法。
但你可以做到以下几点:
for (Iterator<String> i = a.iterator(); i.hasNext();) {
Book next = i.next();
if (book.getISBN() == isbn){
book.returnBook();
i.remove(i);
}
}
同样,复杂性是在这种情况下为O(n^2)。
如果他添加超级粗“i--”,第一个循环会起作用。在if语句的底部。 – 2012-04-01 03:47:10
你是什么意思? – 2012-04-01 03:48:25
在最后一个中,它是从ArrayList中删除还是仅从迭代器中删除? – 2012-04-01 03:53:29
所有很好的答案。但我会让你重新思考它。我的意思是,你真的需要一个ArrayList还是一个HashMap会更好?如果你的对象列表有一个单一关键字(ISBN),并用它来获取每个对象,为什么不使用适合你的问题的集合呢?
你woud只做这
public void returnBook(String isbn){
Book book = (Book) booksBorrowed.remove(isbn);
book.returnBook();
}
如果你的问题是“为什么我得到一个错误”,它是因为您无法从正在迭代的列表中删除项目。如果相同的ISBN可以在列表中两次,您的第一个循环可能会有一个错误。 – 2012-04-01 03:28:19