Quelle est la différence entre ArrayList.clear () et ArrayList.removeAll ()?


283

En supposant que cela arraylistsoit défini comme ArrayList<String> arraylist, est arraylist.removeAll(arraylist)équivalent à arraylist.clear()?

Si oui, puis-je supposer que la clear()méthode est plus efficace pour vider la liste des tableaux?

Y a-t-il des mises en garde à utiliser à la arraylist.removeAll(arraylist)place de arraylist.clear()?


Un corollaire possible à cette question: quand pourrait-on utiliser l'un au lieu de l'autre?
Corey Ogburn

3
@ Corey: quand est-ce que chacun pourrait vouloir l'utiliser arraylist.removeAll(arraylist)? Je ne vois absolument aucune raison de le faire.
Joachim Sauer

@Joachim Sauer C'est exactement ce que je voulais vérifier. Merci +2. Mais la différence entre elementData[i] = nullet est-elle e.remove()significative?
ateiob

Il n'y a aucune raison de sain d' esprit de le faire au arrList.removeAll(arrList)lieu de arrList.clear(). arrList1.removeAll(arrList2)est une autre affaire.
Vlad

3
Si seulement l'implémentation de removeAll () avait commencé avec cette ligne, alors toute cette discussion aurait pu être bien plus divertissante !!! if (c == this && !isEmpty()) { clear(); return true; }. Je vais devoir le soumettre à OpenJDK en tant que patch! ;-)
Julius Musseau

Réponses:


396

Le code source de clear():

public void clear() {
    modCount++;

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

    size = 0;
}

Le code source de removeAll()(tel que défini dans 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() est beaucoup plus rapide car il n'a pas à gérer tous ces appels de méthode supplémentaires.

Et comme le souligne Atrey, c.contains(..)augmente la complexité temporelle de removeAllO (n 2 ) par opposition à clearO (n).


29
Une note qui c.contains(...)évalue la complexité temporelle de l'opération rendrait cette réponse complète.
Atreys

8
La source est forte dans celui-ci. (Pour toutes les autres réponses: utilisez la source, Luke.) Remarquez comment clear () pourrait être implémenté comme une seule ligne, size = 0; mais garbage-collection ne saurait pas collecter les éléments dans les parties inaccessibles du tableau.
Julius Musseau

2
e.remove () est bien plus complexe! e.remove () évalue également la complexité, tout comme c.contains (...). Sur une ArrayList, e.remove () appelle ArrayList.remove (int index), qui doit déplacer le reste du tableau de un.
Julius Musseau

1
@ateiob e.remove () est également deux appels de méthode supplémentaires, une vérification de plage et un retour d'objet (interne à AbstractList.Itr.remove()et ArrayList.remove(int)) également
Atreys

2
@julius Si c'était le cas: size = 0; elementData = new Object[10];tout le reste serait récupéré, car le tableau de sauvegarde n'a pas de références externes.
corsiKa

51

La complexité temporelle de ArrayList.clear()est O(n)et de removeAllest O(n^2).

Alors oui, ArrayList.clearc'est beaucoup plus rapide.


15

La clear()méthode supprime tous les éléments d'un seul ArrayList. C'est une opération rapide, car elle définit simplement les éléments du tableau sur null.

La removeAll(Collection)méthode, héritée de AbstractCollection, supprime tous les éléments qui se trouvent dans la collection d'arguments de la collection sur laquelle vous appelez la méthode. C'est une opération relativement lente, car elle doit rechercher dans l'une des collections impliquées.


Je pensais que cela mettait tout à zéro, pas certains éléments. Si ce n'est pas le cas, comment a-t-il décidé quels éléments devraient être mis à null?
Farid

2
@ Farid désolé, mon anglais est tout simplement trop informel ici. Je voulais en effet dire que cela met tous les éléments à null. Je le réparerai!
Ernest Friedman-Hill

7

À moins qu'il n'y ait une optimisation spécifique qui vérifie si l'argument transmis removeAll()est la collection elle-même (et je doute fortement qu'une telle optimisation soit là), elle sera considérablement plus lente qu'une simple .clear().

En dehors de cela (et au moins tout aussi important): arraylist.removeAll(arraylist)est juste un code obtus et déroutant. C'est une manière très arriérée de dire "effacer cette collection". Quel avantage aurait-il sur le très compréhensible arraylist.clear() ?


7

Ils servent à des fins différentes. clear()efface une instance de la classe, removeAll()supprime tous les objets donnés et retourne l'état de l'opération.


pouvez-vous s'il vous plaît fournir une ressource pour lire sur la question ci-dessus pour une référence
ultérieure

1
@KasunSiyambalapitiya Que diriez-vous de la réponse acceptée , qui contient le code source pour les deux?
Abdul

5

clear() passera par le tableau sous-jacent et définira chaque entrée sur null;

removeAll(collection)passera par ArrayList en vérifiant la collecte et remove(Object)s'il existe.

J'imagine que clear()c'est beaucoup plus rapide que removeAll car ce n'est pas comparer, etc.


2

Clear est plus rapide car il ne boucle pas sur les éléments à supprimer. Cette méthode peut supposer que TOUS les éléments peuvent être supprimés.

Remove allne signifie pas nécessairement supprimer tous les éléments de la liste, seuls ceux fournis en tant que paramètres DEVRAIENT être supprimés. Par conséquent, davantage d'efforts sont nécessaires pour conserver ceux qui ne devraient pas être supprimés.

CLARIFICATION

Par «boucle», je veux dire qu'il n'a pas à vérifier si l'élément doit être conservé ou non. Il peut définir la référence nullsans rechercher dans les listes d'éléments à supprimer fournies.

ClearEST plus rapide que deleteall.


1
Je suis à peu près sûr que cela ArrayList.clear()doit également faire une boucle.
Joachim Sauer

@JVerstry Voulez-vous dire que clear () ne supprime pas les éléments qu'il supprime de la liste de tableaux?
ateiob

1
Mauvais, clear fait une boucle sur le tableau interne et définit toutes les références à null afin de laisser le garbage collector faire son travail.
devconsole

1
@Joachim, @devconsole: Je pense qu'il voulait dire qu'il n'aurait pas à boucler / itérer sur la liste donnée en paramètre. target.removeAll(param)va répéter parampuis appeler target.contains(...)ce qui se répète target.
Vlad

2
-3 est un peu dur. Si JVerstry le voulait, il pourrait écrire sa propre implémentation Java à partir de zéro, sans boucle. clear () peut être implémenté dans O (1), sans boucle, alors que removeAll () DOIT avoir une sorte d'algorithme O (n), il n'y a aucun moyen de satisfaire le contrat de l'API removeAll () sans examiner tous les éléments.
Julius Musseau

1

clear () sera beaucoup plus efficace. Il supprimera simplement chaque élément. L'utilisation de removeAll (arraylist) demandera beaucoup plus de travail car elle vérifiera chaque élément dans arraylist pour voir s'il existe dans arraylist avant de le supprimer.


-8

Array => une fois que l'espace est alloué pour une variable Array au moment de l'exécution, l'espace alloué ne peut pas être étendu ou supprimé.

ArrayList => Ce n'est pas le cas dans arraylist. ArrayList peut croître et se réduire au moment de l'exécution. L'espace alloué peut être minimisé ou maximisé au moment de l'exécution.


Cela ne répond pas à la question qui est la différence entre ArrayList.clear () et ArrayList.removeAll (), pas la différence entre un tableau et un tableau de liste.
Pierre

Cette réponse est inutile. Ce n'est pas de cela qu'il s'agit.
Serafim Costa
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.