Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Eliminar datos de ArrayList con un For-loop

Tengo un problema raro. Pensé que esto me costaría pocos minutos, pero estoy luchando por unas pocas horas ahora … Aquí es lo que tengo:

for (int i = 0; i < size; i++){ if (data.get(i).getCaption().contains("_Hardi")){ data.remove(i); } } 

Los data son ArrayList. En el ArrayList conseguí algunas cuerdas (total 14 o tan), y 9 de ellos, consiguió el nombre _Hardi en él.

Y con el código anterior quiero quitarlos. Si replace data.remove(i); Con un System.out.println entonces imprime algo 9 veces, lo que es bueno, porque _Hardi está en el ArrayList 9 veces.

Pero cuando uso data.remove(i); Entonces no quita todos los 9, pero sólo unos pocos. Hice algunas pruebas y también vi esto:

Cuando renombro las cadenas a: Hardi1 Hardi2 Hardi3 Hardi4 Hardi5 Hardi6

A continuación, elimina sólo los números pares (1, 3, 5 y así sucesivamente). Él está saltando 1 todo el tiempo, pero no puede entender por qué.

¿Alguien sabe cómo solucionar esto? O tal vez otra manera de eliminarlos?

Gracias ya, Bigflow

  • Java - Comparación de clases?
  • Cómo obtener el objeto Mat desde el byte en openCV android?
  • ¿Cómo recibir aleatoriamente un Material Design Color?
  • InputStream a JsonObject - GSON
  • Emulador de Android: Error de instalación: INSTALL_FAILED_VERSION_DOWNGRADE
  • Deserialización de Gson de List <String> en realmList <RealmString>
  • Android Java objModelClass.getClass (). GetDeclaredFields () devuelve "$ change" como un campo
  • Gradle: ¿Cómo puedo incluir un jar local de un proyecto de java dependiente en una compilación de Android?
  • 13 Solutions collect form web for “Eliminar datos de ArrayList con un For-loop”

    El problema aquí es que está iterando de 0 a tamaño y dentro del bucle que está eliminando elementos . Eliminar los elementos reducirá el tamaño de la lista que fallará al intentar acceder a los índices que son mayores que el tamaño efectivo (el tamaño después de los elementos eliminados).

    Hay dos enfoques para hacer esto.

    Elimine utilizando iterador si no desea tratar con el índice.

     for (Iterator<Object> it = data.iterator(); it.hasNext();) { if (it.next().getCaption().contains("_Hardi")) { it.remove(); } } 

    De lo contrario, borrar desde el final.

     for (int i = size-1; i >= 0; i--){ if (data.get(i).getCaption().contains("_Hardi")){ data.remove(i); } } 

    No debe quitar elementos de una lista mientras itera sobre ella. En su lugar, utilice Iterator.remove() como:

     for (Iterator<Object> it = list.iterator(); it.hasNext();) { if ( condition is true ) { it.remove(); } } 

    Cada vez que eliminas un elemento, estás cambiando el índice del que está delante (de modo que al eliminar la lista [1], la lista [2] se convierte en lista [1], de ahí el salto.

    Aquí hay una manera muy fácil de hacerlo: (cuenta atrás en vez de arriba)

    for(int i = list.size() - 1; i>=0; i--) { if(condition...) list.remove(i); }
    for(int i = list.size() - 1; i>=0; i--) { if(condition...) list.remove(i); } 

    Tiene mucho sentido si lo piensas bien. Supongamos que tiene una lista [A, B, C] . El primer paso a través del bucle, i == 0 . Verá el elemento A y luego lo eliminará, por lo que la lista es ahora [B, C] , con el elemento 0 siendo B Ahora incrementas i al final del bucle, por lo que estás viendo la list[1] que es C

    Una solución es decrementar i cada vez que se elimina un elemento, de modo que "cancela" el incremento posterior. Una solución mejor, como los puntos b mate arriba, es usar un Iterator<T> que tiene una función de remove() incorporada.

    Hablando en general, es una buena idea, cuando se enfrenta a un problema como este, sacar un pedazo de papel y fingir que eres la computadora – pasar por cada paso del bucle, escribir todas las variables a medida que vaya. Eso habría hecho el "saltar" claro.

     for (Iterator<Object> it = data.iterator(); it.hasNext();) { if ( it.getCaption().contains("_Hardi")) { it.remove(); // performance is low O(n) } } 

    Si su operación de eliminación se requiere mucho en la lista. Es mejor que use LinkedList que da un mejor rendimiento Big O(1) (aproximadamente).

    Donde en el rendimiento de ArrayList es O(n) (aproximadamente). Por lo tanto, el impacto es muy alto en la operación de extracción.

    Es porque cuando se quita un elemento de una lista, los elementos de la lista se mueven hacia arriba. Así que si quita el primer elemento, es decir, en el índice 0 el elemento en el índice 1 se desplazará al índice 0, pero su contador de bucle seguirá aumentando en cada iteración. Por lo que en lugar de obtener el elemento actualizado 0 º índice obtendrá el primer elemento de índice. Tan apenas disminuye el contador por una cada vez que usted quita un elemento de su lista.

    Puede utilizar el siguiente código para que funcione bien:

     for (int i = 0; i < data.size(); i++){ if (data.get(i).getCaption().contains("_Hardi")){ data.remove(i); i--; } } 

    Es tarde, pero podría funcionar para alguien.

     Iterator<YourObject> itr = yourList.iterator(); // remove all data which you want while (itr.hasNext()) { YourObject object= itr.next(); if (Your Statement) // for ex :object.AutoID == 0 && object.LineDeleted == true { itr.remove(); } } 

    Esto sucede porque al eliminar los elementos se modifica el índice de una ArrayList .

    Porque su índice no es bueno más una vez que elimine un valor

    Por otra parte usted no podrá ir al size puesto que si usted quita un elemento, el tamaño como cambiado.

    Puede usar un iterator para lograrlo.

    Podría también mencionar usted puede también ir sobre esto usando un bucle regular mientras:

     int i = 0; while (i < data.size()) { if (data.get(i).getCaption().contains("_Hardi")) data.remove(i); else i++; } 

    Tenga en cuenta que data.size() debe ser llamado cada vez en la condición de bucle, de lo contrario terminará con un IndexOutOfBoundsException , ya que cada elemento eliminado altera el tamaño original de su lista.

     import java.util.ArrayList; public class IteratorSample { public static void main(String[] args) { // TODO Auto-generated method stub ArrayList<Integer> al = new ArrayList<Integer>(); al.add(1); al.add(2); al.add(3); al.add(4); System.out.println("before removal!!"); displayList(al); for(int i = al.size()-1; i >= 0; i--){ if(al.get(i)==4){ al.remove(i); } } System.out.println("after removal!!"); displayList(al); } private static void displayList(ArrayList<Integer> al) { for(int a:al){ System.out.println(a); } } } 

    salida:

    Antes del retiro !! 1 2 3 4

    Después de la eliminación !! 1 2 3

    No entiendo por qué esta solución es la mejor para la mayoría de la gente.

     for (Iterator<Object> it = data.iterator(); it.hasNext();) { if (it.next().getCaption().contains("_Hardi")) { it.remove(); } } 

    El tercer argumento está vacío, porque se ha movido a la siguiente línea. Además, it.next() no sólo incrementa la variable de loop, sino que también está usando para obtener datos. Para mí el uso for bucle es engañoso. ¿Por qué no usa while ?

     Iterator<Object> it = data.iterator(); while (it.hasNext()) { Object obj = it.next(); if (obj.getCaption().contains("_Hardi")) { it.remove(); } } 

    Hay una manera más fácil de resolver este problema sin crear un nuevo objeto iterador. Aquí está el concepto. Suponga que su arrayList contiene una lista de nombres:

     names = [James, Marshall, Susie, Audrey, Matt, Carl]; 

    Para eliminar todo de Susie adelante, simplemente obtener el índice de Susie y asignarlo a una nueva variable:

     int location = names.indexOf(Susie);//index equals 2 

    Ahora que tiene el índice, dígale a java que cuente el número de veces que quiera quitar valores de la lista de matrices:

     for (int i = 0; i < 3; i++) { //remove Susie through Carl names.remove(names.get(location));//remove the value at index 2 } 

    Cada vez que se ejecuta el valor de bucle, el arrayList se reduce en longitud. Puesto que ha establecido un valor de índice y está contando el número de veces que desea quitar valores, ya está todo configurado. A continuación se muestra un ejemplo de salida después de cada paso:

      [2] names = [James, Marshall, Susie, Audrey, Matt, Carl];//first pass to get index and i = 0 [2] names = [James, Marshall, Audrey, Matt, Carl];//after first pass arrayList decreased and Audrey is now at index 2 and i = 1 [2] names = [James, Marshall, Matt, Carl];//Matt is now at index 2 and i = 2 [2] names = [James, Marshall, Carl];//Carl is now at index 3 and i = 3 names = [James, Marshall,]; //for loop ends 

    Este es un fragmento de lo que su método final puede parecer:

     public void remove_user(String name) { int location = names.indexOf(name); //assign the int value of name to location if (names.remove(name)==true) { for (int i = 0; i < 7; i++) { names.remove(names.get(location)); }//end if print(name + " is no longer in the Group."); }//end method 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.