2012-04-01 18 views
5

ich ein Problem hätte mit einem Objekt aus Arraylist zu löschen, wenn sie auf der Zuweisung arbeitet Wenn ich die „normalen“ for-Schleife verwenden, funktioniert es wie folgtEntfernen Arraylist-Objekt Ausgabe

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);     
     } 
    } 
} 

Allerdings, wenn ich bin versuchen, den Code zu vereinfachen mit for-Schleife verbessert, das nicht funktioniert und zeigt java.util.ConcurrentModificationException Fehler:

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

hoffe, euch zu mir aufhellen könnte ..

+0

Wenn Ihre Frage ist: „Warum bekomme ich einen Fehler“ es ist weil Sie keine Objekte aus einer Liste entfernen können, über die Sie iterieren. Und Ihre erste Schleife kann einen Fehler enthalten, wenn dieselbe ISBN zweimal in der Liste sein kann. –

Antwort

7

Ihre Alternativen eine ConcurrentModificationException zu vermeiden sind:

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"))); 

alle Datensätze sammeln, die Sie auf erweiterte for-Schleife zu löschen, und nach Abschluss Iterieren entfernen Sie alle gefundenen Datensätze.

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); 

Oder Sie können ein ListIterator die Unterstützung während der Iteration selbst für eine remove-Methode hat verwenden.

ListIterator<Book> iter = books.listIterator(); 
while(iter.hasNext()){ 
    if(iter.next().getIsbn().equals(isbn)){ 
     iter.remove(); 
    } 
} 

Oder Sie können eine Drittanbieter-Bibliothek wie LambdaJ verwenden und es macht die ganze Arbeit für Sie hinter die Kulissen>

List<Book> filtered = select(books, 
       having(on(Book.class).getIsbn(), 
         is(new ISBN("0-201-63361-2")))); 
+0

Danke Kumpel, Problem gelöst :) – babygau

+0

Sie sparen mein Leben. Vielen Dank –

4

Das solltest du auch nicht tun, da sie am Ende Probleme verursachen. Verwenden Sie stattdessen den Iterator der ArrayList, um die Liste zu durchlaufen und dann nur mit dem Iterator zu entfernen. Dies wird dazu beitragen, schädliche gleichzeitige Fehler zu vermeiden.

+1

/golfclap Verwendung von 'pernicious' –

0

Wenn Sie die erweiterte for-Schleife in Java verwenden, verwendet sie den Iterator der Liste, um über die Liste zu iterieren. Wenn Sie ein Element mit der remove-Funktion der Liste entfernen, stört dies den Zustand des Iterators, und der Iterator löst eine ConcurrentModificationException aus. Mit der einfachen for-Schleife haben Sie kein solches Problem, weil Sie nur die Liste verwenden und die Statusänderung nur in der Liste selbst auftritt.

+0

Care, um mich ein wenig aufzuklären mit, wie man den Iterator verwendet, um Buchobjekt zu entfernen – babygau

+0

es hängt wirklich davon ab, was Sie Anwendung ist und welche Art Leistung Sie wünschen. Eine Kombination von hashmap und arraylist Iterator wird das tun. – amshali

1

Sie haben einen Fehler im Code:

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

Es nächste Elemente nach entfernt diejenigen überspringt. Z.B. Wenn Sie das Element "0th" entfernen, wird der erste Wert zu 0th, aber dieser Code durchläuft ihn nicht.

Dies ist eine korrekte Version:

for (int i = booksBorrowed.size() - 1; i >= 0; i--){    
    if (booksBorrowed.get(i).getISBN() == isbn){ 
     booksBorrowed.get(i).returnBook(); 
     booksBorrowed.remove(i);     
    } 
} 

Aber das ist nicht der beste Ansatz, weil es die Komplexität ist O (n^2).

Eine bessere Lösung besteht darin, alle beibehaltenen Elemente zu einer anderen Sammlung hinzuzufügen und sie dann mit der abgeschnittenen Größe in die ursprüngliche Liste zu kopieren. Die Komplexität ist O (n). Natürlich ist es nur ein Problem, wenn es viele Elemente zu entfernen gibt.

P.S. Entfernen in einer für jede Konstruktion bricht Iterator, so ist es keine gültige Möglichkeit, die Liste in diesem Fall zu verarbeiten.

Aber Sie können folgendes tun:

for (Iterator<String> i = a.iterator(); i.hasNext();) { 
     Book next = i.next(); 
     if (book.getISBN() == isbn){ 
      book.returnBook(); 
      i.remove(i);     
     } 
    } 

Auch hier ist die Komplexität O (n^2) in diesem Fall.

+0

Erste Schleife funktioniert, wenn er das Uber-Brutto "i--;" am Ende der if-Anweisung. –

+0

was meinst du? –

+0

In der letzten, entfernt es von der ArrayList oder nur aus dem Iterator? –

2

Alle guten Antworten. Aber ich würde dich ermutigen, es zu überdenken. Ich meine, brauchen Sie wirklich eine ArrayList oder eine HashMap wäre besser? Wenn Ihre Liste von Objekten einen Unic Key (ISBN) hat und Sie verwenden, um jedes Objekt zu erhalten, warum verwenden Sie nicht eine für Ihr Problem geeignete Sammlung?

Sie woud nur tun dies

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