ich versuche eine Schleife über eine arrayList zu iterieren, bei der sich der Inhalt der Liste verändert (Elemente der Liste werden unter einer best. Bedingung gelöscht). Da sich durch das Löschen der Elemente innerhalb der Schleife die Indizes der Elemente verändern kann ich keine for-Schleife verwenden und wollte stattdessen die iterator() Methode verwenden. Allerdings kann ich hierbei nicht mehr auf die Elemente der Liste zugreifen. Hier ist das ursprüngliche Problem (mit der for-Schleife, bei der sich die Indizes verschieben nach dem Löschen):
Code:
for(int i = 0; i < agentList.size(); i++){
Agent a = (Agent)agentList.get(i);
if(a.getAttendedGrade() > 4){
a.getNeighborhoodSchool().studentList.remove(a);
int xA1 = a.getX();
int yA1 = a.getY();
world.removeAgentAt(xA1, yA1);
agentList.remove(a);
}
}
}
Hier ist die Variante mit iterator():
Code:
while (it.hasNext()){
Agent a = (Agent)agentList.iterator();
if(a.getAttendedGrade() > 4 ){
a.getNeighborhoodSchool().studentList.remove(a);
int xA1 = a.getX();
int yA1 = a.getY();
world.removeAgentAt(xA1, yA1);
agentList.remove(a);
}
}
}
Hierbei erhalte ich folgende Fehlermeldung:
Exception in thread "Thread-4" java.lang.ClassCastException: java.util.ArrayList$Itr cannot be cast to demo.Agent
Die erste Methode wäre möglich, wenn man rückwärts durchläuft:
Java:
for(int i = agentList.size()-1; i >=0; i--){
Nur für ArrayLists empfohlen (eigendlich wie alle Zählschleifen), LinkedLists haben dabei einen besonders starken Overhead. (Direkter Feldzugriff ist Vorteil ArrayList > LinkedList)
Hier wäre ein agentList.remove(i); besser.
Bei der 2. Methode darfst du keinesfalls (liste).remove sondern nur (iterator).remove() aufrufen.
Iterator it = agentList.iterator();while(it.hasNext()){Agent a =(Agent) it.next();if(a.getAttendedGrade()>4){
a.getNeighborhoodSchool().studentList.remove(a);int xA1 = a.getX();int yA1 = a.getY();
world.removeAgentAt(xA1, yA1);
it.remove();}}// oder seit Java5 etwas eleganter...Iterator<Agent> it = agentList.iterator();while(it.hasNext()){Agent a = it.next();if(a.getAttendedGrade()>4){
a.getNeighborhoodSchool().studentList.remove(a);int xA1 = a.getX();int yA1 = a.getY();
world.removeAgentAt(xA1, yA1);
it.remove();}}
Solange du nicht zwei oder mehr Elemente einer Collection untersuchen musst, ist die Position der Elemente relativ egal.
Sobald man aber zwei Elemente miteinander vergleichen muss, eignet sich die For-Schleife besser. Wenn man dann ein Element entfernt, muss man die Positionszeiger händisch nach unten korregieren.
Vielen Dank Ihr Drei, das war sehr sehr hilfreich. Ich habe alle Methoden probiert und alle haben funktioniert.
@Volvagia: ich musste mir gerade mithilfe von Stiften klarmachen, warum es funktioniert wenn man rückwärts durchläuft (in der Liste rücken ja die oberen Elemente immer nach unten durch wenn man zwischendrin ein Element entfernt).
@Spacerate: mir war tatsächlich nicht klar wie man genau den Iterator benutzt, danke für beide Beispiele mit generics und cast (muss mir generics noch angewöhnen).