while remove iterating from example java collections

iterating - Comportamiento no deseado de ArrayList remove() en Java



remove element from list java (7)

Esta pregunta ya tiene una respuesta aquí:

Tengo los siguientes dos escenarios:

1. int valor como parámetro

int intNum = 2; List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); list.remove(intNum); System.out.println(list.size()); // output: 2

2. valor largo como parámetro

long longNum = 2; List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); list.remove(longNum); System.out.println(list.size()); // output: 3

Estoy pasando 2 como valor en ambos casos, pero obtengo un valor de tamaño diferente de la Lista. ¿Cuál es la razón real de este comportamiento?

La eliminación correcta de un entero de una lista no explica que el tipo de datos incorporado tenga el mismo valor pero que tenga un comportamiento diferente al que se preguntó anteriormente


Calling List.remove () con un argumento int coincidirá con la remove(int index) la firma remove(int index) y el elemento en la list[2] índices list[2] se eliminará independientemente de si la lista tiene un elemento entero con un valor de 2.

Llamar a List.remove () con un argumento largo hará que el compilador realice el boxeo automático en un objeto Long y coincida con la remove(Object o) la firma remove(Object o) . La lista se repetirá, preguntando si hay o.equals (cada elemento) y, como se mencionó anteriormente, Long no es igual a Integer.


Cuando estabas haciendo list.remove(intNum); estaba realizando la remove(int index); Firma de la clase List , que elimina el elemento del índice dado.

Sin embargo, cuando hiciste list.remove(longNum); (considerando que significaba longNum para ser long ), realizó la boolean remove(Object o); Firma de la clase List , que comprueba si el objeto está presente en la lista, y si es así lo elimina.

Como la lista es una lista de Integer no pudo encontrar el objeto y no eliminó nada, y es por eso que el segundo resultado es 3, no se elimina nada.


Desde la documentation List.remove ():

remove (int index) Elimina el elemento en la posición especificada en esta lista (operación opcional).

remove (Objeto o) Elimina la primera aparición del elemento especificado de esta lista, si está presente (operación opcional).

removeAll (Colección c) Elimina de esta lista todos sus elementos que están contenidos en la colección especificada (operación opcional).

Si el segundo ejemplo es realmente largo, no se eliminará (ya que utiliza el segundo método de eliminación).


La interfaz de la List contiene dos métodos remove() : remove(Object) y remove(int) .

La implementación de remove(Object) en Java 6 es la siguiente:

public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }

La implementación de remove(int) en Java 6 es:

public E remove(int index) { RangeCheck(index); modCount++; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; }

En su primer ejemplo, en realidad está llamando al método remove(int) , que elimina el objeto en el índice especificado. En este caso, especificó el índice 2, que en realidad es el valor "3".

En su segundo ejemplo, está llamando al método remove(Object) , ya que no hay un método remove(long) y un long no se convertirá en un int . En función de la implementación del método remove(Object) , busca la igualdad de objetos. Ya que su lista contiene objetos de tipo Integer y está proporcionando un Long , nada lo igualará.

El siguiente método es probablemente un mejor ejemplo de lo que está sucediendo:

public static void main(String[] args) { ArrayList<Integer> list; System.out.println("Removing intNum"); int intNum = 2; list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); System.out.println("List = " + list); list.remove(intNum); System.out.println("List = " + list); System.out.println("Removing longNum"); long longNum = 2; list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); System.out.println("List = " + list); list.remove(longNum); System.out.println("List = " + list); }

La salida de este código es:

Removing intNum List = [1, 2, 3] List = [1, 2] Removing longNum List = [1, 2, 3] List = [1, 2, 3]


La lista en la Colección tiene dos métodos sobrecargados 1. public E remove (int index) 2. public boolean remove (Object o)

En su caso se llama segundo método . ya que está pasando largo (conversión implícita a la clase de contenedor largo , por lo que clase de objeto).

Ahora List.remove (longNum) elimina el elemento con el índice más bajo i, de modo que (longNum == null? Get (i) == null: longNum.equals (get (i))) (si existe dicho elemento).

Ahora en su caso, cuando el contador llegó a la segunda posición (es decir, i = 1). longNum.equals (get (1)) devuelve false porque get (1) devuelve el objeto de java.lang.Integer con value = 2 y longNum es una instancia de java.lang.Long con value = 2. Así que el método igual devuelve falso, por lo que no elimina el elemento.

Puede verificar el tipo de valor por su nombre de clase

System.out.println(" Element Value :"+list.get(1)); System.out.println(" Element Class :"+list.get(1).getClass());


Tenga cuidado: el primero elimina el Integer en el index = 2 . Ver ArrayList.remove(int)

El segundo intenta eliminar un objeto con ArrayList.remove(Object) , pero el objeto que desea eliminar no existe porque es un objeto Long .


Autoboxing

El método list.remove está sobrecargado, y las dos firmas diferentes se utilizan para diferentes propósitos. Uno, list.remove(int) , elimina un elemento en función de su índice, y el otro, list.remove(Object) , elimina un elemento en función de la igualdad de objetos. Su primera situación desencadena el primer tipo, y su segundo ejemplo (con un long longNum ), desencadena el segundo tipo, haciendo un autoboxing de la primitiva long a un objeto java.lang.Long . Esto no es igual a los valores java.lang.Integer (autoboxed) agregados a la lista, por lo que no eliminará nada de la lista y el tamaño seguirá siendo el mismo.