¿Cuál es la diferencia entre ArrayList.clear () y ArrayList.removeAll ()?

283

Suponiendo que arraylistse define como ArrayList<String> arraylist, es arraylist.removeAll(arraylist)equivalente a arraylist.clear()?

Si es así, ¿puedo suponer que el clear()método es más eficiente para vaciar la lista de la matriz?

¿Hay alguna advertencia en el uso en arraylist.removeAll(arraylist)lugar de arraylist.clear()?

ateiob
fuente
Un posible corolario a esta pregunta: ¿cuándo podría usarse uno en lugar del otro?
Corey Ogburn
3
@Corey: ¿cuándo podría uno querer usar arraylist.removeAll(arraylist)? No veo absolutamente ninguna razón para hacer eso.
Joachim Sauer
@Joachim Sauer Eso es exactamente lo que quería verificar. Gracias +2. ¿Pero es la diferencia entre elementData[i] = nully e.remove()significativo?
ateiob
No hay una razón sensata para hacer en arrList.removeAll(arrList)lugar de arrList.clear(). arrList1.removeAll(arrList2)Es un asunto diferente.
Vlad
3
Si solo la implementación de removeAll () comenzara con esta línea, ¡entonces toda esta discusión podría haber sido mucho más entretenida! if (c == this && !isEmpty()) { clear(); return true; }. ¡Tendré que enviar esto a OpenJDK como un parche! ;-)
Julius Musseau

Respuestas:

396

El código fuente para clear():

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

El código fuente de removeAll()(Como se define en AbstractCollection):

public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    Iterator<?> e = iterator();
    while (e.hasNext()) {
        if (c.contains(e.next())) {
            e.remove();
            modified = true;
        }
    }
    return modified;
}

clear() es mucho más rápido ya que no tiene que lidiar con todas esas llamadas a métodos adicionales.

Y como señala Atrey, c.contains(..)aumenta la complejidad temporal de removeAllO (n 2 ) en oposición a clearO (n).

Jeffrey
fuente
29
Una nota que c.contains(...)cuadre la complejidad temporal de la operación completaría esta respuesta.
Atreys
8
La fuente es fuerte en este. (Para todas las demás respuestas: use la fuente, Luke.) Observe cómo clear () podría implementarse como una sola línea, tamaño = 0; pero la recolección de basura no sabría recolectar los elementos en las partes inalcanzables de la matriz.
Julius Musseau
2
¡e.remove () es mucho más complejo! e.remove () también cuadra la complejidad, al igual que c.contains (...). En una ArrayList, e.remove () llama a ArrayList.remove (int index), que tiene que desplazar el resto de la matriz por uno.
Julius Musseau
1
@ateiob e.remove () son dos llamadas a métodos adicionales, una verificación de rango y un retorno de objeto (interno a AbstractList.Itr.remove()y ArrayList.remove(int)) también
Atreys
2
@julius Si hiciera esto: size = 0; elementData = new Object[10];todo el resto sería basura recolectada, ya que la matriz de respaldo no tiene referencias externas.
corsiKa
51

La complejidad temporal de ArrayList.clear()es O(n)y deremoveAll es O(n^2).

Entonces sí, ArrayList.cleares mucho más rápido.

Geoff
fuente
15

El clear()método elimina todos los elementos de un solo ArrayList. Es una operación rápida, ya que solo establece los elementos de la matriz ennull .

El removeAll(Collection)método, que se hereda AbstractCollection, elimina todos los elementos que están en la colección de argumentos de la colección a la que llama el método. Es una operación relativamente lenta, ya que tiene que buscar en una de las colecciones involucradas.

Ernest Friedman-Hill
fuente
Pensé que simplemente establece todo, no algunos elementos como nulos. Si no es el caso, ¿cómo decidió qué elementos deben establecerse en nulo?
Farid
2
@Farid lo siento, mi inglés es demasiado informal aquí. De hecho, quise decir que establece todos los elementos en nulo. ¡Lo arreglaré!
Ernest Friedman-Hill
7

A menos que haya una optimización específica que verifique si el argumento pasado removeAll()es la colección en sí (y dudo mucho que tal optimización esté ahí), será significativamente más lenta que una simple .clear().

Aparte de eso (y al menos igualmente importante): arraylist.removeAll(arraylist)es un código obtuso y confuso. Es una forma muy retrasada de decir "borrar esta colección". ¿Qué ventaja tendría sobre lo muy comprensible arraylist.clear() ?

Joachim Sauer
fuente
7

Sirven para diferentes propósitos. clear()borra una instancia de la clase, removeAll()elimina todos los objetos dados y devuelve el estado de la operación.

lucapette
fuente
puede usted por favor proporcionar un recurso para leer sobre el asunto arriba para referencia futher
Kasun Siyambalapitiya
1
@KasunSiyambalapitiya ¿Qué tal la respuesta aceptada , que contiene el código fuente para los dos?
Abdul
5

clear() pasará por la matriz subyacente y establecerá cada entrada en nulo;

removeAll(collection) pasará por ArrayList buscando la colección y remove(Object) si existe.

Me imagino que clear()es mucho más rápido que eliminar todo porque no se compara, etc.

Nicholas
fuente
2

Clear es más rápido porque no recorre los elementos para eliminar. Este método puede suponer que TODOS los elementos se pueden eliminar.

Remove allno significa necesariamente eliminar todos los elementos de la lista, solo aquellos provistos como parámetros DEBERÍAN eliminarse. Por lo tanto, se requiere más esfuerzo para mantener aquellos que no deben eliminarse.

ACLARACIÓN

Por "bucle", quiero decir que no tiene que verificar si el elemento debe mantenerse o no. Puede establecer la referencia anull sin buscar en las listas de elementos proporcionadas para eliminar.

ClearES más rápido que deleteall.

Jérôme Verstrynge
fuente
1
Estoy bastante seguro de que eso también ArrayList.clear()tiene que repetirse.
Joachim Sauer
@JVerstry ¿Quiere decir que clear () no elimina los elementos que elimina de ArrayList?
ateiob
1
Incorrecto, clear realiza un bucle sobre la matriz interna y establece todas las referencias en nulo para permitir que el recolector de basura haga su trabajo.
devconsole
1
@Joachim, @devconsole: Creo que quiso decir que no tendrá que recorrer / iterar sobre la lista dada como parámetro. target.removeAll(param)iterará paramy luego llamará a target.contains(...)cuál itera target.
Vlad
2
-3 es un poco duro. Si JVerstry quisiera, podría escribir su propia implementación de Java desde cero que no se repitiera. clear () puede implementarse de manera factible en O (1), sin un bucle, mientras que removeAll () DEBE tener algún tipo de algoritmo O (n), no hay forma de satisfacer el contrato de API removeAll () sin examinar todos los elementos.
Julius Musseau
1

clear () será mucho más eficiente. Simplemente eliminará todos y cada uno de los elementos. El uso de removeAll (arraylist) requerirá mucho más trabajo porque verificará todos los elementos de arraylist para ver si existe en arraylist antes de eliminarlo.

CDelaney
fuente
-8

Array => una vez que se asigna el espacio para una variable Array en el tiempo de ejecución, el espacio asignado no se puede extender ni eliminar.

ArrayList => Este no es el caso en arraylist. ArrayList puede crecer y reducirse en el tiempo de ejecución. El espacio asignado se puede minimizar o maximizar en el tiempo de ejecución.

Arun Kumar
fuente
Esto no responde a la pregunta, que es la diferencia entre ArrayList.clear () y ArrayList.removeAll (), no la diferencia entre un Array y un ArrayList.
Pierre
Esta respuesta es innecesaria. De eso no se trata la pregunta.
Serafim Costa