Para recorrer ArrayList
hemos estando usando for-each
.
Por ejemplo, en la clase GestorPersonas
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void addSamplePersons(){
Persona p;
p = new Persona("Pepe", "M");
addPersona(p);
p = new Persona("Juan", "J");
addPersona(p);
p = new Persona("Ana", "A");
addPersona(p);
p = new Persona("Julia", "J");
addPersona(p);
}
public void printPersons(String search){
for (Persona p : personas){
if (p.getNombre().contains(search)){
System.out.println(p);
}
}
}
Ahora suponed que pretendemos borrar de la lista aquellas personas que tengan un determinado patrón en el nombre.
Podemos buscar la ayuda de ArrayList
y observamos que tiene un método llamado remove(O o)
que elimina la primera ocurrencia del objeto o
en la lista.
Así que es muy sencillo borrar un elemento de la lista:
1
2
3
4
5
6
7
8
public void removePersonsForeach(String search){
for (Persona p : personas){
if (p.getNombre().contains(search)){
//Usamos el método remove para eliminar el objeto
personas.remove(p);
}
}
}
Vamos a crear un nuevo objecto GestorPersonas
y llamar al método removePersonsForeach("u")
;
Pero ocurre lo siguiente:
Nos ha lanzado la excepción java.util.ConcurrentModificationException
. Esto es normal: no se puede borrar ningún elemento de un ArrayList
usando un for-each
.
¿Por qué ocurre esto?
Suponed que la lista tiene 4 personas y la 3 persona queremos borrarla. Al hacer un for-each
, cuando borramos la 3, la lista ahora tiene 3 elementos en vez de 4!! y el elemento 4 se ha convertido en el 3.
Podemos solucionarlo usando un bucle for
:
1
2
3
4
5
6
7
8
9
10
public void removePersonsFor(String search){
for(int i = 0; i < personas.size(); i++){
Persona p = personas.get(i);
if (p.getNombre().contains(search)){
personas.remove(i);
//Ahora el índice lo decremento en 1.
i--;
}
}
}
Pero la solución extendida en Java es usar Iteradores. Hemos de importar la clase import java.util.Iterator;
Y ahora creamos el método con Iteradores:
1
2
3
4
5
6
7
8
9
public void removePersonsIterator(String search){
Iterator<Persona> it = personas.iterator();
while (it.hasNext()) {
Persona p = it.next();
if(p.getNombre().contains(search)){
it.remove();
}
}
}
Los ArrayList
y otras colecciones de java tienen un método que devuelve un Iterator
Este Iterator
siempre se recorre de la misma forma:
1
2
3
4
5
Iterator<TipoElemento> it = miLista.iterator();
while (it.hasNext()) {
// llamar a it.next() para obtener el siguiente elemento;
// hacer algo con ese elemento;
}
Ahora ya podemos usar it.remove()
porque no salta ninguna excepción al llamar a remove()