Quand utiliser LinkedList over ArrayList en Java?

j'ai toujours été du genre à utiliser simplement:

List<String> names = new ArrayList<>();

j'utilise l'interface comme nom de type pour portabilité , de sorte que lorsque je pose des questions comme celles-ci, je peux retravailler mon code.

"quand utiliser LinkedList plutôt que ArrayList et vice-versa?

2624
demandé sur Steve Chambers 2008-11-27 04:36:35

30 réponses

Résumé ArrayList avec ArrayDeque est préférable à beaucoup plus de cas d'utilisation de LinkedList . Si vous n'êtes pas sûr, commencez par ArrayList .


LinkedList et ArrayList sont deux implémentations différentes de L'interface de liste. LinkedList l'implémente avec une liste doublement liée. ArrayList l'implémente avec un tableau de re-dimensionnement dynamique.

comme pour les opérations de liste et de tableau liées standard, les différentes méthodes auront des durées d'exécution algorithmiques différentes.

pour LinkedList<E>

  • get(int index) est O(n) (avec les n/4 les étapes de la moyenne)
  • add(E element) is O(1)
  • add(int index, E element) est O(n) (avec n/4 pas en moyenne), mais O (1) quand index = 0 < - - - principal avantage de LinkedList<E>
  • remove(int index) est O(n) (avec les n/4 les étapes de la moyenne)
  • Iterator.remove() est O(1) . < - - - principal avantage de LinkedList<E>
  • ListIterator.add(E element) est O(1) C'est l'un des principaux avantages de LinkedList<E>

Remarque: la plupart des opérations de besoin n/4 les étapes de la moyenne", constante nombre d'étapes dans le meilleur des cas (p. ex., indice = 0), et n/2 étapes dans le pire des cas (milieu de la liste)

pour ArrayList<E>

  • get(int index) est O(1) <--- principal avantage de la ArrayList<E>
  • add(E element) est O(1) amorti, mais O(n) pire-cas depuis le tableau doit être redimensionnée et copié
  • add(int index, E element) est O(n) (avec les n/2 les étapes de la moyenne)
  • remove(int index) est O(n) (avec n/2 pas en moyenne)
  • Iterator.remove() est O(n) (avec les n/2 les étapes de la moyenne)
  • ListIterator.add(E element) est O(n) (avec les n/2 les étapes de la moyenne)

Note: de nombreuses opérations nécessitent n / 2 pas en moyenne, constante nombre d'étapes dans le meilleur des cas (fin de liste), n dans le pire des cas (début de la liste)

LinkedList<E> permet des insertions ou des suppressions à temps constant en utilisant des itérateurs , mais seulement l'accès séquentiel des éléments. En d'autres termes, vous pouvez parcourir la liste en avant ou en arrière, mais de trouver une position dans la liste prend du temps proportionnel à la taille de la liste. Javadoc dit "les opérations qui indexent dans la liste traverseront la liste depuis le début ou la fin, celle qui est la plus proche" , donc ces méthodes sont O(n) ( n/4 steps) en moyenne, bien que o(1) pour index = 0 .

ArrayList<E> , d'autre part, permettent un accès rapide au hasard de lecture, de sorte que vous pouvez saisir n'importe quel élément en temps constant. Mais l'ajout ou le retrait de n'importe où mais la fin nécessite déplacer tous ces derniers éléments, soit pour faire une ouverture, soit pour combler le vide. En outre, si vous ajoutez plus d'éléments que la capacité du tableau sous-jacent, un nouveau tableau (1,5 fois la taille) est alloué, et l'ancien tableau est copié sur le nouveau, donc l'ajout à un ArrayList est O(n) dans le pire des cas mais constante en moyenne.

ainsi, selon les opérations que vous avez l'intention de faire, vous devez choisir les implémentations en conséquence. Itérer concernant soit le type de Liste est pratiquement aussi bon marché. (Itérer sur un ArrayList est techniquement plus rapide, mais à moins que vous ne fassiez quelque chose de vraiment sensible aux performances, vous ne devriez pas vous en inquiéter -- ce sont deux constantes.)

les principaux avantages de l'utilisation d'un LinkedList apparaissent lorsque vous réutilisez des itérateurs existants pour insérer et supprimer des éléments. Ces opérations peuvent alors être effectuées dans O(1) en changeant la liste localement seulement. Dans un tableau list, le reste du tableau doit être déplacé (c'est-à-dire copié). De l'autre côté, chercher dans un LinkedList signifie suivre les liens dans O(n) ( n/2 steps) pour le pire des cas, tandis que dans un ArrayList la position désirée peut être calculée mathématiquement et accessible dans o(1) .

un autre avantage de l'utilisation d'un LinkedList se produit lorsque vous ajoutez ou retirez de la chef de la liste, puisque ces opérations sont O(1) , alors qu'ils sont O(n) pour ArrayList . Notez que ArrayDeque peut être une bonne alternative à LinkedList pour ajouter et enlever de la tête, mais ce n'est pas un List .

Aussi, si vous avez de grandes listes, gardez à l'esprit que l'utilisation de la mémoire est également différente. Chaque élément d'un LinkedList a plus de overhead puisque les pointeurs vers les éléments suivants et précédents sont également stockées. ArrayLists Je n'ai pas ces frais généraux. Toutefois, ArrayLists absorbe autant de mémoire que la capacité attribuée, que des éléments aient été ajoutés ou non.

la capacité initiale par défaut d'un ArrayList est assez faible (10 de Java 1.4 - 1.8). Mais puisque l'implémentation sous-jacente est un tableau, le tableau doit être redimensionné si vous ajoutez beaucoup d'éléments. Pour éviter le coût élevé de redimensionnement lorsque vous savez que vous allez à ajouter beaucoup de elements, construire le ArrayList avec une plus grande capacité initiale.

2895
répondu Jonathan Tran 2018-09-11 21:00:26

jusqu'à présent, personne ne semble avoir abordé l'empreinte mémoire de chacune de ces listes à part le consensus général qu'un LinkedList est" beaucoup plus "qu'un ArrayList donc j'ai fait quelques calculs pour montrer exactement combien les deux listes prennent pour n références nulles.

puisque les références sont 32 ou 64 bits (même si nul) sur leurs systèmes relatifs, j'ai inclus 4 ensembles de données pour 32 et 64 bits LinkedLists et ArrayLists .

Note: les tailles indiquées pour les lignes ArrayList correspondent aux listes tronquées - en pratique, la capacité du backing-array dans un ArrayList est généralement plus grande que son nombre actuel d'éléments.

Note 2: (merci BeeOnRope) comme CompressedOops est par défaut à partir de mid JDK6 et plus, les valeurs ci-dessous pour les machines 64 bits seront essentiellement correspondent à leurs homologues 32 bits, à moins bien sûr que vous éteignez spécifiquement.


Graph of LinkedList and ArrayList No. of Elements x Bytes


le résultat montre clairement que LinkedList est beaucoup plus que ArrayList , surtout avec un nombre d'éléments très élevé. Si la mémoire est un facteur, évitez LinkedLists .

les formules que j'ai utilisées suivent, faites-moi savoir si j'ai fait quelque chose de mal et je vais le corriger. "b" est 4 ou 8 pour les systèmes 32 ou 64 bits, et " n " est le nombre d'éléments. Notez que la raison pour les mods est que tous les objets en java prendront un multiple de 8 octets d'espace, qu'ils soient tous utilisés ou non.

ArrayList :

ArrayList object header + size integer + modCount integer + array reference + (array oject header + b * n) + MOD(array oject, 8) + MOD(ArrayList object, 8) == 8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8) + MOD(8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8), 8)

LinkedList :

LinkedList object header + size integer + modCount integer + reference to header + reference to footer + (node object overhead + reference to previous element + reference to next element + reference to element) * n) + MOD(node object, 8) * n + MOD(LinkedList object, 8) == 8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n + MOD(8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n, 8)
543
répondu Numeron 2017-05-02 11:00:53

ArrayList est ce que vous voulez. LinkedList est presque toujours un bug (de performance).

pourquoi LinkedList craint:

  • il utilise beaucoup de petits objets de mémoire, et affecte donc la performance tout au long du processus.
  • beaucoup de petits objets sont mauvais pour cache-locality.
  • toute opération indexée nécessite une opération transversale, c'est-à-dire une performance O(n). Ce n'est pas évident dans la source code, conduisant à des algorithmes O(n) plus lent que si ArrayList a été utilisé.
  • obtenir une bonne performance est délicat.
  • même si la performance du big-O est la même que celle du ArrayList , elle sera probablement beaucoup plus lente de toute façon.
  • il est troublant de voir LinkedList dans la source parce que c'est probablement le mauvais choix.
197
répondu Tom Hawtin - tackline 2017-10-09 13:27:37

en tant que quelqu'un qui a fait l'ingénierie de performance opérationnelle à très grande échelle SOA web services depuis environ une décennie, je préférerais le comportement de LinkedList plutôt que ArrayList. Alors que le débit stable de LinkedList est pire et pourrait donc conduire à acheter plus de matériel -- le comportement de ArrayList sous pression pourrait conduire à des applications dans un cluster d'étendre leurs réseaux en quasi synchronicité et pour les grandes tailles de réseaux pourrait conduire à un manque de réactivité dans l'application et une panne, sous pression, ce qui est un comportement catastrophique.

de la même manière, vous pouvez obtenir un meilleur débit dans une application à partir du débit par défaut collecteur de déchets tenured, mais une fois que vous obtenez des applications java avec des tas de 10 Go, vous pouvez finir par verrouiller l'application pendant 25 secondes pendant un GCs complet qui provoque des arrêts de durée et des échecs dans les applications SOA et souffle vos SLAs si elle se produit trop souvent. Même si le collecteur CMS prend plus de ressources et n'atteint pas la même le débit, c'est un bien meilleur choix parce qu'il a une latence plus prévisible et plus petite.

ArrayList est seulement un meilleur choix pour la performance si tout ce que vous entendez par performance est le débit et vous pouvez ignorer la latence. D'après mon expérience à mon travail, je ne peux pas ignorer la pire des latences.

125
répondu lamont 2011-01-01 20:23:52
Algorithm           ArrayList   LinkedList
seek front            O(1)         O(1)
seek back             O(1)         O(1)
seek to index         O(1)         O(N)
insert at front       O(N)         O(1)
insert at back        O(1)         O(1)
insert after an item  O(N)         O(1)

Algorithmes: Big-Oh Notation

ArrayLists sont bons pour l'écriture-une fois-lire-beaucoup ou appenders, mais mauvais à ajouter/enlever de l'avant ou au milieu.

111
répondu Michael Munsey 2016-07-28 08:46:18

Oui, je sais, c'est une question ancienne, mais je vais jeter dans mes deux cents:

LinkedList est presque toujours le mauvais choix, en terme de performance. Il existe des algorithmes très spécifiques pour lesquels une liste de liens est nécessaire, mais ceux-ci sont très, très rares et l'algorithme dépendra généralement spécifiquement de la capacité de LinkedList à insérer et supprimer des éléments au milieu de la liste relativement rapidement, une fois que vous y aurez navigué avec un ListIterator.

il existe un cas d'usage courant dans lequel LinkedList dépasse ArrayList: celui d'une file d'attente. Cependant, si votre objectif est la performance, au lieu de LinkedList, vous devriez également envisager d'utiliser un ArrayBlockingQueue (si vous pouvez déterminer une limite supérieure sur votre taille de file d'attente à l'avance, et pouvez vous permettre d'allouer toute la mémoire à l'avance), ou ce CircularArrayList implementation . (Oui, c'est de 2001, donc vous aurez besoin de le généraliser, mais je

94
répondu Daniel Martin 2009-05-19 11:21:20

c'est une question d'efficacité. LinkedList est rapide pour ajouter et supprimer des éléments, mais lent pour accéder à un élément spécifique. ArrayList est rapide pour accéder à un élément spécifique, mais peut être lente, à ajouter à chaque extrémité, et particulièrement lente à supprimer dans le milieu.

Array vs ArrayList vs LinkedList vs Vector va plus en profondeur, comme le fait Liste .

51
répondu dgtized 2018-04-20 06:12:45

Correct ou Incorrect: veuillez exécuter le test localement et décider vous-même!

Edit / Remove est plus rapide dans LinkedList que dans ArrayList .

ArrayList , soutenu par Array , qui doit être le double de la taille, est pire dans l'application de grand volume.

ci-dessous est le résultat de l'essai unitaire pour chaque opération.Le Timing est donné en nanosecondes.


Operation                       ArrayList                      LinkedList  

AddAll   (Insert)               101,16719                      2623,29291 

Add      (Insert-Sequentially)  152,46840                      966,62216

Add      (insert-randomly)      36527                          29193

remove   (Delete)               20,56,9095                     20,45,4904

contains (Search)               186,15,704                     189,64,981

voici le code:

import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class ArrayListVsLinkedList {
    private static final int MAX = 500000;
    String[] strings = maxArray();

    ////////////// ADD ALL ////////////////////////////////////////
    @Test
    public void arrayListAddAll() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        arrayList.addAll(stringList);
        watch.totalTime("Array List addAll() = ");//101,16719 Nanoseconds
    }

    @Test
    public void linkedListAddAll() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);

        watch.start();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);
        watch.totalTime("Linked List addAll() = ");  //2623,29291 Nanoseconds
    }

    //Note: ArrayList is 26 time faster here than LinkedList for addAll()

    ///////////////// INSERT /////////////////////////////////////////////
    @Test
    public void arrayListAdd() {
        Watch watch = new Watch();
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        for (String string : strings)
            arrayList.add(string);
        watch.totalTime("Array List add() = ");//152,46840 Nanoseconds
    }

    @Test
    public void linkedListAdd() {
        Watch watch = new Watch();

        List<String> linkedList = new LinkedList<String>();
        watch.start();
        for (String string : strings)
            linkedList.add(string);
        watch.totalTime("Linked List add() = ");  //966,62216 Nanoseconds
    }

    //Note: ArrayList is 9 times faster than LinkedList for add sequentially

    /////////////////// INSERT IN BETWEEN ///////////////////////////////////////

    @Test
    public void arrayListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX + MAX / 10);
        arrayList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        arrayList.add(insertString0);
        arrayList.add(insertString1);
        arrayList.add(insertString2);
        arrayList.add(insertString3);

        watch.totalTime("Array List add() = ");//36527
    }

    @Test
    public void linkedListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        linkedList.add(insertString0);
        linkedList.add(insertString1);
        linkedList.add(insertString2);
        linkedList.add(insertString3);

        watch.totalTime("Linked List add = ");//29193
    }


    //Note: LinkedList is 3000 nanosecond faster than ArrayList for insert randomly.

    ////////////////// DELETE //////////////////////////////////////////////////////
    @Test
    public void arrayListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.remove(searchString0);
        arrayList.remove(searchString1);
        watch.totalTime("Array List remove() = ");//20,56,9095 Nanoseconds
    }

    @Test
    public void linkedListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.remove(searchString0);
        linkedList.remove(searchString1);
        watch.totalTime("Linked List remove = ");//20,45,4904 Nanoseconds
    }

    //Note: LinkedList is 10 millisecond faster than ArrayList while removing item.

    ///////////////////// SEARCH ///////////////////////////////////////////
    @Test
    public void arrayListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.contains(searchString0);
        arrayList.contains(searchString1);
        watch.totalTime("Array List addAll() time = ");//186,15,704
    }

    @Test
    public void linkedListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.contains(searchString0);
        linkedList.contains(searchString1);
        watch.totalTime("Linked List addAll() time = ");//189,64,981
    }

    //Note: Linked List is 500 Milliseconds faster than ArrayList

    class Watch {
        private long startTime;
        private long endTime;

        public void start() {
            startTime = System.nanoTime();
        }

        private void stop() {
            endTime = System.nanoTime();
        }

        public void totalTime(String s) {
            stop();
            System.out.println(s + (endTime - startTime));
        }
    }


    private String[] maxArray() {
        String[] strings = new String[MAX];
        Boolean result = Boolean.TRUE;
        for (int i = 0; i < MAX; i++) {
            strings[i] = getString(result, i);
            result = !result;
        }
        return strings;
    }

    private String getString(Boolean result, int i) {
        return String.valueOf(result) + i + String.valueOf(!result);
    }
}
49
répondu Ash 2018-04-20 06:23:23

ArrayList est essentiellement un tableau. LinkedList est implémenté sous la forme d'une liste double liée.

le get est assez clair. O (1) pour ArrayList , parce que ArrayList permettent un accès aléatoire en utilisant index. O (n) pour LinkedList , parce qu'il a besoin de trouver l'index en premier. Note: il existe différentes versions de add et remove .

LinkedList est plus rapide dans add et remove, mais plus lent dans get. En bref, LinkedList devrait être préféré si:

  1. il n'y a pas grand nombre de l'accès aléatoire de l'élément
  2. il y a un grand nombre d'ajouter/supprimer des opérations

=== ArrayList = = =

  • ajouter(E e)
    • ajouter à la fin de ArrayList
    • nécessite un coût de redimensionnement de la mémoire.
    • O(n) sur les pires, O(1) amorti
  • ajouter (index int, élément E))
    • ajouter à une position d'index spécifique
    • exiger le déplacement et la mémoire possible redimensionnement coût
    • O (n)
  • supprimer (index int)
    • supprimer un élément spécifié
    • nécessitent un déplacement et un possible redimensionnement de la mémoire coût
    • O (n)
  • supprimer (objet o)
    • supprimer la première occurrence de l'élément spécifié de cette liste
    • besoin de rechercher l'élément en premier, puis déplacement et de la mémoire possible redimensionnement coût
    • O (n)

=== LinkedList = = =

  • ajouter(E)

    • ajouter à la fin de la liste
    • O (1)
  • add (int index, e element)

    • insérer à la position spécifiée
    • besoin de trouver la position en premier
    • O (n)
  • supprimer()
    • supprimer le premier élément de la liste
    • O (1)
  • supprimer (index int)
    • supprimer l'élément avec l'index spécifié
    • besoin de trouver l'élément en premier
    • O (n)
  • supprimer (objet o)
    • supprimer la première occurrence de l'élément spécifié
    • besoin de trouver l'élément d'abord
    • O (n)

Voici un schéma de programcreek.com ( add et remove sont du premier type, c'est à dire, ajouter un élément à la fin de la liste et supprimer l'élément à la position spécifiée dans la liste.):

enter image description here

40
répondu Ryan 2018-05-27 10:29:49

ArrayList est accessible au hasard, tandis que LinkedList est vraiment bon marché pour étendre et supprimer des éléments. Pour la plupart des cas, ArrayList est très bien.

sauf si vous avez créé de grandes listes et mesuré un goulot d'étranglement, vous n'aurez probablement jamais besoin de se soucier de la différence.

30
répondu Dustin 2018-04-20 06:14:16

1) Recherche: ArrayList opération de recherche est assez rapide par rapport à la LinkedList opération de recherche. get(int index) in ArrayList donne la performance de O(1) alors que la performance LinkedList est O (n).

raison: ArrayList maintient un système basé sur l'index pour ses éléments car il utilise implicitement la structure de données de tableau ce qui le rend plus rapide pour la recherche d'un élément dans la liste. De l'autre côté, LinkedList implémente une liste doublement liée qui nécessite la traversée de tous les éléments pour la recherche d'un élément.

2) Deletion: LinkedList supprimer opération donne O(1) la performance tandis que ArrayList donne la performance variable: O(n) dans le pire des cas (tout en enlevant le premier élément) et O(1) dans le meilleur des cas (tout en enlevant le dernier élément).

Conclusion: la suppression de l'élément de la liste de liens est plus rapide que Liste de tableaux.

raison: chacun des éléments de LinkedList contient deux pointeurs (adresses), qui pointent vers les deux éléments voisins de la liste. Ainsi que l'enlèvement nécessite un changement dans la position du pointeur dans les deux nœuds voisins (éléments) du noeud qui va être supprimé. Alors que dans ArrayList tous les éléments doivent être décalés pour remplir l'espace créé par l'élément enlevé.

3) Insère La Performance: LinkedList ajouter une méthode donne O(1) les performances tout en ArrayList donne O(n) dans le pire des cas. La raison en est même comme il est expliqué pour les supprimer.

4) mémoire aérienne: ArrayList maintient des indices et des données d'élément tandis que LinkedList maintient des données d'élément et deux pointeurs pour les noeuds voisins donc la consommation de mémoire est élevée dans LinkedList comparativement.

Il y a quelques similitudes entre ces classes sont les suivantes:

les deux tableaux ArrayList et LinkedList sont des implémentations de L'interface List. Ils maintiennent tous les deux l'ordre d'insertion des éléments, ce qui signifie que tout en affichant les éléments ArrayList et LinkedList, le résultat serait d'avoir le même ordre dans lequel les éléments ont été insérés dans la liste. Ces deux classes ne sont pas synchronisées et peuvent être rendues explicitement synchronisées en utilisant Collections.synchronizedList méthode. L'itérateur et le listiterateur les retours par ces classes sont rapides (si la liste est structurellement modifiée à tout moment après la création de l'itérateur, de quelque manière que ce soit sauf par les propres méthodes de suppression ou d'ajout de l'itérateur, l'itérateur lancera une exception de modification Concurrentemodificationexception).

quand utiliser LinkedList et quand utiliser ArrayList?

1) comme expliqué ci-dessus, les opérations d'insertion et de suppression donnent de bonnes performances (O(1)) dans LinkedList par rapport à ArrayList(O (n)). Par conséquent, s'il y a une exigence d'ajout et de suppression fréquents dans une application, alors LinkedList est le meilleur choix.

2) les opérations de recherche (méthode get) sont rapides dans ArrayList (O(1)) mais pas dans LinkedList (O(n)) donc S'il y a moins d'opérations d'ajout et de suppression et plus d'opérations de recherche nécessaires, ArrayList serait votre meilleur pari.

29
répondu NoNaMe 2018-07-24 17:18:07

Joshua Bloch, l'auteur de LinkedList:

est-ce que quelqu'un utilise réellement LinkedList? Je l'ai écrit, et je ne l'utilise jamais.

lien: https://twitter.com/joshbloch/status/583813919019573248

je suis désolé que la réponse ne soit pas aussi informative que les autres réponses, mais j'ai pensé que ce serait la plus intéressante et explicite.

24
répondu Ruslan 2017-04-25 10:23:06

je sais que c'est un vieux post, mais honnêtement je ne peux pas croire que personne n'a mentionné que LinkedList met en œuvre Deque . Il suffit de regarder les méthodes de Deque (et Queue ); si vous voulez une comparaison équitable, essayez d'exécuter LinkedList contre ArrayDeque et de fonctionnalités de comparaison.

18
répondu Ajax 2018-04-20 06:29:50

si votre code a add(0) et remove(0) , utilisez un LinkedList et c'est plus joli addFirst() et removeFirst() méthodes. Sinon, utilisez ArrayList .

Et bien sûr, Goyave 's ImmutableList est votre meilleur ami.

17
répondu Jesse Wilson 2018-04-20 06:16:46

Voici la notation Big-O dans les deux ArrayList et LinkedList et aussi CopyOnWrite-ArrayList :

ArrayList

get                 O(1)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

LinkedList

get                 O(n)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(1)
iterator.remove     O(1)

CopyOnWrite-Liste De Tableaux

get                 O(1)
add                 O(n)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

sur la base de ceux-ci, vous devez décider quoi choisir. :)

15
répondu Rajith Delantha 2018-04-20 06:29:10

comparons LinkedList et ArrayList W. R. T. paramètres ci-dessous:

1. La mise en œuvre

ArrayList est le redimensionnable de la matrice de mise en œuvre de la liste de l'interface , alors que

LinkedList est l'implémentation de liste doublement liée de l'interface de liste.


2. Performance

  • get(int index) ou de l'opération de recherche

    ArrayList get(int index) operation runs in constant time I. 151910920"

    LinkedList get(int index) fonctionnement temps d'exécution est O(n) .

    la raison pour laquelle ArrayList est plus rapide que LinkedList est que ArrayList utilise un index basé système pour ses éléments comme il utilise à l'interne une structure de données de tableau, d'autre part,

    LinkedList ne fournit pas d'accès par index pour l'un de ses éléments qu'il itère au début ou à la fin (selon la valeur la plus proche) pour récupérer le nœud à l'index de l'élément.

  • insert() ou add(Objet) de l'opération

    Insertions LinkedList sont généralement aussi rapides que comparer à ArrayList. Dans LinkedList ajouter ou insérer est O(1) opération .

    alors que dans ArrayList , si le tableau est le I. dans le pire des cas, il y a un coût supplémentaire pour redimensionner le tableau et copier des éléments dans le nouveau tableau, ce qui rend l'exécution de l'opération add dans ArrayList O(n), sinon C'est O(1).

  • supprimer(int) opération

    Supprimer l'opération dans LinkedList est généralement la même que ArrayList i.e. O(n).

    Dans LinkedList , il y a deux surchargé méthodes de suppression. l'un est remove () sans aucun paramètre qui supprime la tête de liste et s'exécute en temps constant O (1). L'autre méthode de suppression surchargée dans LinkedList est remove(int) ou remove (Object) qui supprime L'objet ou int passé en paramètre. Cette méthode traverse l' LinkedList jusqu'à ce qu'il trouve l'objet et le désolidarise de la liste originale. Par conséquent, la durée d'exécution de cette méthode est O(n).

    alors que dans ArrayList la méthode remove(int) implique de copier des éléments de l'ancien tableau vers le nouveau tableau mis à jour, donc son exécution est O(n).


3. Itérateur Inversé

LinkedList peut être itéré en sens inverse en utilisant descendingIterator () alors que

il n'y a pas de descendant() dans ArrayList , donc nous avons besoin d'écrire notre propre code pour itérer au-dessus de L'ArrayList en sens inverse.


4. Capacité Initiale

si le constructeur n'est pas surchargé, alors ArrayList crée une liste vide de capacité initiale 10, tandis que

LinkedList ne construit que la liste vide sans aucune capacité initiale.


5. Mémoire Aérienne

surcharge de la Mémoire dans LinkedList est plus par rapport à l'ArrayList comme un nœud dans LinkedList pour maintenir les adresses de la prochaine et nœud précédent. Alors que

dans ArrayList chaque index ne contient que l'objet réel(données).


Source

11
répondu Abhijeet Ashok Muneshwar 2018-07-24 15:49:31

en plus des autres bons arguments ci-dessus, vous devriez noter ArrayList met en œuvre RandomAccess interface, tandis que LinkedList met en œuvre Queue .

donc, d'une certaine façon ils abordent des problèmes légèrement différents, avec une différence d'efficacité et de comportement (voir leur liste de méthodes).

10
répondu PhiLho 2018-04-20 06:15:53

une liste de tableaux est essentiellement un tableau avec des méthodes pour ajouter des éléments, etc. (et vous devez utiliser une liste générique à la place). Il s'agit d'un ensemble d'éléments accessibles par l'intermédiaire d'un indexeur (par exemple [0]). Elle implique une progression d'un point à l'autre.

une liste liée spécifie une progression d'un point à l'autre (point a -> point b). Vous pouvez obtenir le même effet avec une liste de tableau, mais une liste liée absolument dit à quel point est censé suivre le précédente.

6
répondu kemiller2002 2010-04-20 15:32:01

cela dépend des opérations que vous ferez plus sur la liste.

ArrayList est plus rapide pour accéder à une valeur indexée. C'est bien pire quand on insère ou supprime des objets.

Pour en savoir plus, lisez l'article qui parle de la différence entre les tableaux et les listes chaînées.

6
répondu Matthew Schinckel 2018-04-20 06:14:59

j'ai lu les réponses, mais il y a un scénario où j'utilise toujours une Lienedlist sur un ArrayList que je veux partager pour entendre des opinions:

chaque fois que j'ai eu une méthode qui retourne une liste de données obtenues à partir d'un DB, j'utilise toujours une Likedlist.

mon raisonnement était que parce qu'il est impossible de savoir exactement combien de résultats je reçois, il n'y aura pas de mémoire gaspillée (comme dans ArrayList avec la différence entre la capacité et nombre réel d'éléments), et il n'y aurait pas de temps perdu à essayer de dupliquer la capacité.

en ce qui concerne un ArrayList, je suis d'accord qu'au moins vous devriez toujours utiliser le constructeur avec la capacité initiale, pour minimiser la duplication des tableaux autant que possible.

5
répondu gaijinco 2011-10-03 23:23:00

Une caractéristique importante d'une liste chaînée (que je n'ai pas lu dans une autre réponse) est la concaténation de deux listes. Avec un tableau c'est O(n) (+frais généraux de quelques réallocations) avec une liste liée c'est seulement O(1) ou O (2); -)

Important : pour Java son LinkedList ce n'est pas vrai! Voir Existe-t-il une méthode de concat rapide pour la liste liée en Java?

5
répondu Karussell 2017-05-23 12:02:46

L'opération get (i) dans ArrayList est plus rapide que LinkedList, car:

ArrayList: Resizable-array implementation of the List interface

LinkedList: Doubly-linked list implementation of the List and Deque interfaces

opérations qui indexent dans la liste parcourra la liste depuis le début ou la fin, selon la plus proche de l'index spécifié.

5
répondu Amitābha 2016-11-09 10:48:34

ArrayList et LinkedList les deux instruments List interface et leurs méthodes et résultats sont presque identiques. Cependant, il ya quelques différences entre eux qui font mieux sur l'autre en fonction des besoins.

ArrayList Vs LinkedList

1) Search: ArrayList l'opération de recherche est assez rapide comparée à l'opération de recherche LinkedList . get(int index) dans ArrayList donne la performance de O(1) alors que LinkedList performance est O(n) .

Reason: ArrayList maintient le système basé sur l'index pour ses éléments car il utilise implicitement la structure de données de tableau ce qui le rend plus rapide pour la recherche d'un élément dans la liste. De l'autre côté LinkedList implémente une liste doublement liée qui nécessite la traversée de tous les éléments pour la recherche d'un élément.

2) Deletion: LinkedList enlever l'opération donne O(1) , tandis que ArrayList donne des performances variables: O(n) dans le pire des cas (en enlevant le premier élément) et O(1) dans le meilleur des cas (en enlevant le dernier élément).

Conclusion: la suppression de L'élément LinkedList est plus rapide que Liste de tableaux.

raison: chaque élément de LinkedList contient deux pointeurs (adresses) qui pointent vers les deux éléments voisins de la liste. D'où la suppression seulement exige le changement dans la position du pointeur dans les deux nœuds voisins (éléments) du noeud qui va être supprimé. Alors que dans ArrayList tous les éléments doivent être décalés pour remplir l'espace créé par l'élément enlevé.

3) Inserts Performance: LinkedList la méthode add donne la performance O(1) tandis que ArrayList donne la performance O(n) dans le pire des cas. La raison est la même que celle expliquée pour supprimer.

4) Memory Overhead: ArrayList maintient les indices et les données d'élément tandis que LinkedList maintient les données d'élément et deux pointeurs pour les noeuds voisins

donc la consommation de mémoire est élevée dans LinkedList comparativement.

il y a peu de similitudes entre ces classes qui sont les suivantes:

  • les deux tableaux ArrayList et LinkedList sont la mise en œuvre de L'interface de liste.
  • ILS deux maintenir l'ordre d'insertion des éléments, ce qui signifie que tout en affichant les éléments ArrayList et LinkedList, le résultat serait d'avoir le même ordre dans lequel les éléments ont été insérés dans la liste.
  • ces deux classes sont non-synchronisées et peuvent être synchronisées explicitement en utilisant des Collections.synchronizedList méthode.
  • les iterator et listIterator renvoyés par ces classes sont fail-fast (si la structure de la liste est modifiée à à tout moment après la création de l'itérateur, de quelque manière que ce soit, sauf par le biais des méthodes iterator’s propres supprimer ou ajouter, l'itérateur sera throw a ConcurrentModificationException ).

quand utiliser LinkedList et quand utiliser ArrayList?

  • comme expliqué ci-dessus, les opérations d'insertion et de suppression donnent de bonnes performances (O(1)) dans LinkedList par rapport à ArrayList(O(n)) .

    donc s'il y a une exigence d'ajout et de suppression fréquents dans l'application puis LinkedList est un meilleur choix.

  • recherche ( get method ) les opérations sont rapides dans Arraylist (O(1)) mais pas dans LinkedList (O(n))

    donc S'il y a moins d'opérations add et remove et plus d'opérations de recherche nécessaires, ArrayList serait votre meilleur pari.

4
répondu Real73 2016-11-02 09:00:23

ArrayList et LinkedList ont leurs propres avantages et inconvénients.

ArrayList utilise une adresse mémoire contiguë par rapport à LinkedList qui utilise des pointeurs vers le prochain noeud. Ainsi, lorsque vous voulez rechercher un élément dans un ArrayList est plus rapide que de faire n itérations avec LinkedList.

d'un autre côté, l'insertion et la suppression dans une liste de liens sont beaucoup plus faciles parce que vous avez juste à changer les pointeurs tandis qu'un ArrayList implique l'utilisation de opération de déplacement pour toute insertion ou suppression.

si vous avez des opérations de récupération fréquentes dans votre application utilisez un ArrayList. Si vous avez l'insertion et la suppression fréquentes utiliser une liste de liens.

4
répondu Nesan Mano 2017-10-21 01:58:43

1) Structure De Données Sous-Jacente

la première différence entre ArrayList et LinkedList vient du fait que ArrayList est soutenue par Array tandis que LinkedList est soutenue par LinkedList. Il en résultera d'autres différences de rendement.

2) LinkedList implements Deque

une autre différence entre ArrayList et LinkedList est qu'en dehors de la liste interface, LinkedList implémente également deque interface, qui fournit les premières opérations de sortie pour add() et poll() et plusieurs autres fonctions Deque. 3) Ajouter des éléments dans ArrayList Ajouter un élément dans ArrayList est une opération O(1) si elle ne déclenche pas la re-Taille du tableau, auquel cas elle devient O(log(n)), d'autre part, Ajouter un élément dans LinkedList est une opération O(1), car il ne nécessite pas de navigation.

4) Retrait d'un élément d'un position

afin de supprimer un élément d'un index particulier, par exemple en appelant supprimer(index), ArrayList effectue une opération de copie qui le rend proche de O(n) tandis que LinkedList doit traverser ce point qui le rend également O(n/2), car il peut traverser de l'une ou l'autre direction basée sur la proximité.

5) itération sur ArrayList ou LinkedList

itération est l'opération O(n) pour à la fois LinkedList et ArrayList où n est un nombre d'un élément.

6) Elément récupérant d'une position

l'opération get(index) est O(1) dans ArrayList tandis que son O(n/2) dans LinkedList, car il doit parcourir jusqu'à cette entrée. Cependant, dans la notation Big O O (n / 2) est juste O(n) parce que nous ignorons les constantes là.

7) mémoire

LinkedList utilise un wrapper object, Entry, qui est une classe statique imbriquée pour stocker des données et deux noeuds suivant et précédent tandis que ArrayList stocke juste des données dans Array.

ainsi l'exigence de mémoire semble moindre dans le cas de ArrayList que LinkedList sauf dans le cas où Array effectue l'opération de Re-size quand il copie le contenu d'un Array à un autre.

si le tableau est assez grand il peut prendre beaucoup de mémoire à ce point et déclencher la collecte des ordures, qui peuvent temps de réponse lent.

de toutes les différences ci-dessus entre ArrayList vs LinkedList, il semble que ArrayList est le meilleur choix que LinkedList dans presque tous les cas, sauf quand vous faites une opération fréquente add() que remove(), ou get().

il est plus facile de modifier une liste liée que ArrayList, surtout si vous ajoutez ou supprimez des éléments du début ou de la fin parce que la liste liée garde en interne les références de ces positions et qu'elles sont accessibles en O(1) fois.

en d'autres termes, vous n'avez pas besoin de parcourir la liste liée pour atteindre la position où vous voulez ajouter des éléments, dans ce cas, l'ajout devient O(n) opération. Par exemple, insérer ou supprimer un élément au milieu d'une liste liée.

à mon avis, utiliser ArrayList over LinkedList pour la plupart des fins pratiques en Java.

2
répondu Anjali Suman 2018-07-24 16:01:05

les systèmes remove() et insert() ont tous deux une efficacité d'exécution O(n) pour les tableaux et les listes reliées. Toutefois, la raison derrière le temps de traitement linéaire vient de deux raisons très différentes:

dans un ArrayList, vous arrivez à L'élément dans O(1), mais en fait enlever ou insérer quelque chose le rend O(n) parce que tous les éléments suivants doivent être changés.

dans une liste de liens, il faut O (n) pour obtenir l'élément désiré, parce que nous devons commencer par le début, jusqu'à ce que nous atteignons l'indice désiré. En fait, supprimer ou insérer est constant, car il suffit de changer 1 référence pour supprimer() et 2 références pour insérer().

lequel des deux est le plus rapide pour insérer et enlever dépend de l'endroit où il se produit. Si nous sommes plus proches du début, la liste de liens sera plus rapide, parce que nous devons passer par relativement peu d'éléments. Si nous sommes plus près de la fin, un ArrayList sera plus rapide., parce que nous y arriver à temps constant et de ne changer que les quelques éléments qui suivent. Lorsqu'elle est faite précisément au milieu, la liste de liens sera plus rapide parce que passer en revue les éléments n est plus rapide que de déplacer les valeurs n.

Bonus: bien qu'il n'y ait aucun moyen de rendre ces deux méthodes O(1) pour un ArrayList, il y a en fait un moyen de le faire dans LinkedLists. Disons que nous voulons passer en revue toute la liste en enlevant et en insérant des éléments sur notre chemin. Habituellement, vous commencerait dès le début pour chaque élément en utilisant la LinkedList, nous pourrions également "enregistrer" l'élément courant sur lequel nous travaillons avec un itérateur. Avec L'aide de L'itérateur, nous obtenons une efficacité O(1) pour remove() et insert() lorsque nous travaillons dans une liste de liens. Ce qui en fait le seul avantage de performance que je connaisse où une LinkedList est toujours meilleure qu'une ArrayList.

1
répondu pietz 2018-07-24 16:14:23

ArrayList s'étend AbstractList et met en œuvre la Liste de l'Interface. ArrayList est un réseau dynamique.

On peut dire qu'il a été essentiellement créé pour surmonter les inconvénients de tableaux



La classe LinkedList étend AbstractSequentialList et implémente L'interface List,Deque et Queue.

Performance

arraylist.get() est O(1) tandis que linkedlist.get() est O(n)

arraylist.add() est O(1) et linkedlist.add() est 0(1)

arraylist.contains() est O(n) et linkedlist.contains() est O(n)

arraylist.next() est O(1) et linkedlist.next() est O(1)

arraylist.remove() est O(n) alors que le linkedlist.remove() est O(1)

Dans arraylist

iterator.remove() est O(n)

tandis que dans linkedlist

iterator.remove() est O(1)

0
répondu Randhawa 2018-02-20 21:51:19

L'un des tests que j'ai vu ici ne le fait qu'une seule fois. Mais ce que j'ai remarqué, c'est que vous devez exécuter ces tests plusieurs fois et éventuellement leurs temps convergeront. En gros, la JVM a besoin de se réchauffer. Pour mon cas d'utilisation particulier j'ai besoin d'ajouter/supprimer des éléments d'un dernier qui pousse à environ 500 articles. Dans mes tests, LinkedList est sorti plus vite, avec LinkedList lié à environ 50 000 NS et ArrayList à environ 90 000 NS... donner ou prendre. Voir le code dessous.

public static void main(String[] args) {
    List<Long> times = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        times.add(doIt());
    }
    System.out.println("avg = " + (times.stream().mapToLong(x -> x).average()));
}

static long doIt() {
    long start = System.nanoTime();
    List<Object> list = new LinkedList<>();
    //uncomment line below to test with ArrayList
    //list = new ArrayList<>();
    for (int i = 0; i < 500; i++) {
        list.add(i);
    }

    Iterator it = list.iterator();
    while (it.hasNext()) {
        it.next();
        it.remove();
    }
    long end = System.nanoTime();
    long diff = end - start;
    //uncomment to see the JVM warmup and get faster for the first few iterations
    //System.out.println(diff)
    return diff;
}
0
répondu Jose Martinez 2018-08-04 18:52:06

Quand dois-je utiliser LinkedList ? Lorsque vous travaillez surtout avec des piles, ou lorsque vous travaillez avec des tampons. Quand dois-je utiliser ArrayList ? Seulement quand vous travaillez avec des index, sinon vous pouvez utiliser le HashTable avec la liste liée, alors vous obtenez:

table de hachage + liste liée

  • accès par clé O (1),
  • insérer par la touche O (1),
  • supprimer par clé O (1)
  • et il y a un truc pour implémenter RemoveAll / SetAll avec O (1) en utilisant versioning

Il semble comme une bonne solution, et dans la plupart des cas, il est, comment jamais vous devez savoir: HashTable prend beaucoup d'espace disque, donc quand vous avez besoin de gérer 1.000.000 liste d'éléments, il peut devenir une chose qui importe. Cela peut se produire dans les implémentations de serveur, chez les clients c'est rarement le cas.

regardez aussi Arbre Rouge-Noir

  • accès Aléatoire Log(n),
  • insérer Log (n),
  • Supprimer Log (n)
-1
répondu Ilya Gazman 2016-11-03 12:05:44