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

6 minutos de lectura

avatar de usuario
ateiob

Asumiendo que arraylist Se define como ArrayList<String> arraylistes arraylist.removeAll(arraylist) equivalente a arraylist.clear()?

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

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

  • Un posible corolario de esta pregunta: ¿cuándo podría usarse uno en lugar del otro?

    –Corey Ogburn

    11 de agosto de 2011 a las 20:04

  • @Corey: ¿cuándo uno podría querer usar arraylist.removeAll(arraylist)? No veo absolutamente ninguna razón para hacer eso.

    – Joaquín Sauer

    11 de agosto de 2011 a las 20:07

  • @Joachim Sauer Eso es exactamente lo que quería verificar. Gracias +2. Pero es la diferencia entre elementData[i] = null y e.remove() ¿importante?

    – ateiob

    11 de agosto de 2011 a las 20:12


  • No hay razón sana para hacerlo arrList.removeAll(arrList) en vez de arrList.clear(). arrList1.removeAll(arrList2) es un asunto diferente.

    – Vlad

    11 de agosto de 2011 a las 20:15

  • Si tan solo la implementación de removeAll() comenzara con esta línea, ¡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! 😉

    – Julio Musseau

    11/08/2011 a las 20:31


avatar de usuario
jeffrey

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 para 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 removeAll a O(n2) Opuesto a clear‘s O(n).

  • una nota que c.contains(...) cuadrados, la complejidad temporal de la operación haría que esta respuesta fuera completa.

    – Atreys

    11 de agosto de 2011 a las 20:09


  • La fuente es fuerte en este. (Para todas las demás respuestas: use la fuente, Luke). Observe cómo clear() podría implementarse como solo una línea, tamaño = 0; pero la recolección de basura no sabría recolectar los elementos en las partes inalcanzables de la matriz.

    – Julio Musseau

    11 de agosto de 2011 a las 20:14

  • ¡e.remove() es mucho más complejo! e.remove() también eleva al cuadrado la complejidad, tal como lo hace c.contains(…). En una ArrayList, e.remove() llama a ArrayList.remove(int index), que tiene que desplazar el resto de la matriz en uno.

    – Julio Musseau

    11 de agosto de 2011 a las 20:18


  • @ateiob e.remove() son dos llamadas de método adicionales, una verificación de rango y un retorno de objeto (interno a AbstractList.Itr.remove() y ArrayList.remove(int)), también

    – Atreys

    11 de agosto de 2011 a las 20:19


  • @julius Si hizo 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

    11 de agosto de 2011 a las 20:25

avatar de usuario
Geoff

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

Entonces sí, ArrayList.clear es mucho más rápido.

avatar de usuario
Ernest Friedman-Hill

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

los removeAll(Collection) método heredado de 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.

  • Pensé que simplemente establece todo, no algunos elementos en nulo. Si no es el caso, ¿cómo decidió qué elementos deben establecerse como nulos?

    – Farid

    5 oct 2019 a las 14:10

  • @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

    5 de octubre de 2019 a las 14:12

A menos que haya una optimización específica que verifique si el argumento pasó a removeAll() es la colección en sí (y yo altamente duda de que exista tal optimización) será significativamente más lento que un simple .clear().

Aparte de eso (y al menos igualmente importante): arraylist.removeAll(arraylist) es solo un código obtuso y confuso. Es una forma muy al revés de decir “limpiar esta colección”. ¿Qué ventaja tendría sobre el muy comprensible arraylist.clear()?

avatar de usuario
lucapette

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.

  • ¿Puede proporcionar un recurso para leer sobre el asunto anterior para futuras referencias?

    – Kasun Siyambalapitiya

    2 de febrero de 2017 a las 10:09

  • @KasunSiyambalapitiya ¿Qué tal la respuesta aceptada, que contiene el código fuente de los dos?

    – Honinbo Shusaku

    11 mayo 2017 a las 17:57

avatar de usuario
Nicolás

clear() pasará por el Array subyacente y establecerá cada entrada en nulo;

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

me imagino que clear() es mucho más rápido que removeAll porque no está comparando, etc.

  • ¿Puede proporcionar un recurso para leer sobre el asunto anterior para futuras referencias?

    – Kasun Siyambalapitiya

    2 de febrero de 2017 a las 10:09

  • @KasunSiyambalapitiya ¿Qué tal la respuesta aceptada, que contiene el código fuente de los dos?

    – Honinbo Shusaku

    11 mayo 2017 a las 17:57

Borrar 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 all no significa necesariamente eliminar todos los elementos de la lista, solo los proporcionados como parámetros DEBERÍAN eliminarse. Por lo tanto, se requiere un mayor esfuerzo para mantener aquellos que no deben eliminarse.

ACLARACIÓN

Por ‘bucle’, quiero decir que no tiene que verificar si el elemento debe conservarse o no. Puede establecer la referencia a null sin buscar en las listas proporcionadas de elementos para eliminar.

Clear ES más rápido que deleteall.

  • Estoy bastante seguro de que ArrayList.clear() tiene que hacer un bucle también.

    – Joaquín Sauer

    11 de agosto de 2011 a las 20:04

  • @JVerstry ¿Quieres decir eso claro ()? no elimina los elementos que elimina de ArrayList?

    – ateiob

    11 de agosto de 2011 a las 20:04


  • Incorrecto, clear hace un bucle sobre la matriz interna y establece todas las referencias en nulo para permitir que el recolector de elementos no utilizados haga su trabajo.

    – consola de desarrollo

    11 de agosto de 2011 a las 20:05

  • @Joachim, @devconsole: creo que quiso decir que no tendrá que repetir/iterar sobre la lista dada como parámetro. target.removeAll(param) iterará sobre param y luego llamar target.contains(...) que itera sobre target.

    – Vlad

    11 de agosto de 2011 a las 20:12


  • -3 es un poco duro. Si JVerstry quisiera, podría escribir su propia implementación de Java desde cero que no se repita. claro() pueden factiblemente implementado 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 la API removeAll() sin examinar todos los elementos.

    – Julio Musseau

    11 de agosto de 2011 a las 20:26


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad