Próbuję zrozumieć, dlaczego ArrayDeque w Javie jest lepszy niż LinkedList w Javie, ponieważ oba implementują interfejs Deque.
Prawie nie widzę kogoś używającego ArrayDeque w swoim kodzie. Gdyby ktoś rzucił więcej światła na sposób implementacji ArrayDeque, byłoby to pomocne.
Jeśli to rozumiem, będę pewniej go używać. Nie mogłem jasno zrozumieć implementacji JDK co do sposobu, w jaki zarządza ona odniesieniami głównymi i końcowymi.
java
deque
linked-list
arraydeque
Okrutny
źródło
źródło
src.zip
. Jest to archiwum z kodem źródłowym klas java. Zdecydowanie polecam przestudiowanie struktury tych klas i elementów wewnętrznych, aby lepiej zrozumieć, jak działają klasy Java.Odpowiedzi:
Struktury połączone są prawdopodobnie najgorszymi strukturami do iteracji z brakiem pamięci podręcznej dla każdego elementu. Do tego zużywają znacznie więcej pamięci.
Jeśli potrzebujesz dodać / usunąć oba końce, ArrayDeque jest znacznie lepsza niż lista połączona. Dostęp losowy do każdego elementu jest również O (1) dla cyklicznej kolejki.
Jedyną lepszą operacją na połączonej liście jest usunięcie bieżącego elementu podczas iteracji.
źródło
LinkedList
wdraża,List
gdyArrayDeque
nie. Oznacza to, żeLinkedList
istnieją metody takie jakindexOf
lub,remove(int)
gdyArrayDeque
nie ma. Czasami może to być ważne.Uważam, że głównym wąskim gardłem wydajności
LinkedList
jest fakt, że za każdym razem, gdy naciskasz na dowolny koniec deque, za sceną implementacja przydziela nowy węzeł połączonej listy, który zasadniczo obejmuje JVM / OS, a to jest drogie. Ponadto za każdym razem, gdy wyskakujesz z dowolnego końca, wewnętrzne węzłyLinkedList
kwalifikują się do zbierania śmieci, a to więcej pracy za kulisami. Ponadto, ponieważ węzły listy połączonej są przydzielane tu i tam, użycie pamięci podręcznej procesora nie zapewni większych korzyści.Jeśli to może być interesujące, mam dowód, że dodanie (dołączenie) elementu do
ArrayList
lubArrayDeque
działa w zamortyzowanym stałym czasie; odnoszą się do tego .źródło
ArrayDeque
jest nowością w Javie 6, dlatego wiele kodu (zwłaszcza projektów, które starają się być kompatybilne z wcześniejszymi wersjami Javy) nie używa go.W niektórych przypadkach jest to „lepsze”, ponieważ nie przydzielasz węzła dla każdego wstawianego elementu; zamiast tego wszystkie elementy są przechowywane w gigantycznej tablicy, której rozmiar jest zmieniany, jeśli się zapełni.
źródło
Wszyscy ludzie, którzy krytykują a
LinkedList
, myślą o każdym innym facecie, który używałList
w Javie, prawdopodobnie używa goArrayList
i przezLinkedList
większość czasu, ponieważ byli przed Java 6 i dlatego, że są to te, których uczy się na początku w większości książek.Ale to nie znaczy, będę ślepo brać
LinkedList
„lub SArrayDeque
” s stronie. Jeśli chcesz wiedzieć, spójrz na poniższy benchmark wykonany przez Briana .Konfiguracja testowa uwzględnia:
Wynik testu:
Wykres:
Na wynos:
ArrayList
lubArrayDeque
z dobrym szacunkiem maksymalnej pojemności, jaką może być wymagana lista ze względu na ścisłe ograniczenie pamięci.LinkedList
taką ostrożnością przy podejmowaniu decyzji o użyciu,ArrayDeque
zwłaszcza dlatego, że NIE implementujeList
interfejsu (myślę, że to wystarczająco duży powód). Może się zdarzyć, że twój kod źródłowy intensywnie komunikuje się z interfejsem List, najprawdopodobniej i zdecydujesz się wskoczyć z plikiemArrayDeque
. Używanie go do wewnętrznych wdrożeń może być dobrym pomysłem ...źródło
ArrayDeque i LinkedList implementują Deque interfejs , ale implementacja jest inna.
Kluczowe różnice:
ArrayDeque klasa jest skalowalny realizacja tablica z deque interfejsu i LinkedList klasa jest realizacja lista
Elementy NULL można dodawać do LinkedList, ale nie w ArrayDeque
ArrayDeque jest wydajniejszy niż LinkedList do dodawania i usuwania operacji na obu końcach, a implementacja LinkedList jest wydajna do usuwania bieżącego elementu podczas iteracji
LinkedList realizacja zużywa więcej pamięci niż ArrayDeque
Więc jeśli nie musisz obsługiwać elementów NULL i szukasz mniejszej ilości pamięci i wydajności dodawania / usuwania elementów na obu końcach, ArrayDeque jest najlepszym
Więcej informacji można znaleźć w dokumentacji .
źródło
header.previous.element
). Twierdzenie „wydajność pamięci” może również zostać zakwestionowane, ponieważ rozmiar tablicy bazowej jest zawsze zmieniany do następnej potęgi 2.Iterator
aby uzyskać dostęp do ostatniego elementu, operacja jest O (N) dla obu klas. Kiedy używasz wspólnegoDeque
interfejsu, dostęp do ostatniego elementu jest O (1) dla obu klas. Niezależnie od przyjętego punktu widzenia, przypisywanie O (1) doArrayDeque
i O (N)LinkedList
jednocześnie jest błędne.chociaż
ArrayDeque<E>
iLinkedList<E>
mają zaimplementowanyDeque<E>
interfejs, ale ArrayDeque używa w zasadzie tablicy ObjectE[]
do przechowywania elementów wewnątrz obiektu, więc generalnie używa indeksu do lokalizowania elementów head i tail.Jednym słowem, działa podobnie jak Deque (ze wszystkimi metodami Deque), jednak wykorzystuje strukturę danych tablicy. To, który z nich jest lepszy, zależy od tego, jak i gdzie ich używasz.
źródło
Nie zawsze tak jest.
Na przykład w poniższym przypadku
linkedlist
ma lepszą wydajność niżArrayDeque
zgodnie z leetcode 103.źródło
Złożoność czasowa dla ArrayDeque dostępu do elementu wynosi O (1), a dla LinkList wynosi O (N), aby uzyskać dostęp do ostatniego elementu. ArrayDeque nie jest bezpieczny dla wątków, więc ręczna synchronizacja jest konieczna, aby można było uzyskać do niego dostęp przez wiele wątków i aby były szybsze.
źródło
LinkedList
w JavieCollection
, jest on podwójnie połączony i ma szybki dostęp do głowy i ogona, więc dostęp do ostatniego elementu również wymaga O (1).