I've selalu menjadi salah satu untuk hanya menggunakan:
List<String> names = new ArrayList<>();
Saya menggunakan antarmuka seperti jenis nama untuk portability, sehingga ketika saya mengajukan pertanyaan-pertanyaan seperti ini saya bisa mengolah kode saya.
Ketika harus LinkedList
dapat digunakan lebih dari ArrayList
dan sebaliknya?
Ringkasan ArrayList
dengan ArrayDeque
yang lebih dalam banyak lebih banyak menggunakan-kasus dari LinkedList
. Jika anda're tidak yakin — mulai saja dengan ArrayList
.
LinkedList
dan ArrayList
adalah dua implementasi yang berbeda dari Daftar antarmuka. LinkedList
mengimplementasikannya dengan doubly-linked list. ArrayList
mengimplementasikannya dengan dinamis re-sizing array.
Seperti dengan standar linked list dan array operasi, berbagai metode akan memiliki berbagai algoritma runtime.
Untuk LinkedList<E>
get(int index)
adalah O(n) (dengan n/4 langkah-langkah pada rata-rata)add(int index, E elemen)
adalah O(n) (dengan n/4 langkah-langkah pada rata-rata),
tapi O(1) ketika index = 0
<--- manfaat utama dari LinkedList<E>
remove(int index)
adalah O(n) (dengan n/4 langkah-langkah pada rata-rata)Iterator.hapus()
adalah O(1). <--- manfaat utama dari LinkedList<E>
ListIterator.tambahkan(E elemen)
adalah O(1) Ini adalah salah satu manfaat utama dari LinkedList<E>
Catatan: Banyak operasi perlu n/4 langkah-langkah pada rata-rata, konstan jumlah langkah dalam kasus terbaik (misalnya indeks = 0), dan n/2 langkah-langkah dalam kasus terburuk (tengah daftar)
Untuk ArrayList<E>
get(int index)
adalah O(1) <--- manfaat utama dari ArrayList<E>
add(int index, E elemen)
adalah O(n) (dengan n/2 langkah-langkah pada rata-rata)remove(int index)
adalah O(n) (dengan n/2 langkah-langkah pada rata-rata)Iterator.hapus()
adalah O(n) (dengan n/2 langkah-langkah pada rata-rata)ListIterator.tambahkan(E elemen)
adalah O(n) (dengan n/2 langkah-langkah pada rata-rata)Catatan: Banyak operasi perlu n/2 langkah-langkah pada rata-rata, konstan jumlah langkah dalam kasus terbaik (akhir dari list), n langkah-langkah dalam kasus terburuk (mulai dari daftar)
LinkedList<E>
memungkinkan untuk konstan-waktu insersi atau kepindahan menggunakan iterator, tapi hanya akses sekuensial dari elemen. Dengan kata lain, anda dapat berjalan kaki daftar ke depan atau ke belakang, tapi menemukan sebuah posisi dalam daftar membutuhkan waktu yang proporsional untuk ukuran klik disini. Javadoc kata "operasional yang naik ke dalam daftar akan melintasi daftar dari awal, atau akhir, yang mana yang lebih dekat", sehingga metode tersebut O(n) (n/4 langkah-langkah) pada rata-rata, meskipun O(1) untuk index = 0
.
ArrayList<E>
, di sisi lain, memungkinkan cepat akses baca acak, sehingga anda dapat mengambil setiap elemen dalam waktu yang konstan. Tetapi menambahkan atau menghapus dari mana saja tetapi akhir memerlukan pergeseran semua kedua elemen di atas, baik untuk membuat sebuah lubang atau mengisi kesenjangan. Juga, jika anda menambahkan elemen lebih dari kapasitas yang mendasari array, array (1,5 kali ukuran) dialokasikan, dan array yang lama disalin ke yang baru, sehingga menambah ArrayList
adalah O(n) dalam kasus terburuk tapi konstan pada rata-rata.
Jadi tergantung pada operasi yang anda berniat untuk melakukannya, anda harus memilih implementasi yang sesuai. Iterasi kedua jenis Daftar ini praktis sama-sama murah. (Iterasi lebih dari sebuah ArrayList
secara teknis lebih cepat, tapi kecuali anda're melakukan sesuatu yang benar-benar kinerja yang sensitif, anda tidak't khawatir tentang hal ini-mereka're kedua konstanta.)
Manfaat utama dari menggunakan LinkedList
muncul ketika anda kembali menggunakan iterator untuk menyisipkan dan menghapus elemen. Operasi ini dapat dilakukan di O(1) dengan mengubah daftar lokal saja. Dalam array daftar, sisa array perlu pindah (yaitu disalin). Di sisi lain, mencari dalam LinkedList
berarti mengikuti link di O(n) (n/2 langkah-langkah) untuk kasus terburuk, sedangkan dalam ArrayList
posisi yang diinginkan dapat dihitung secara matematis dan diakses di O(1).
Manfaat lain dari menggunakan LinkedList
muncul bila anda menambahkan atau menghapus dari kepala dari daftar, karena operasi-operasi yang O(1), sementara mereka O(n) untuk ArrayList
. Perhatikan bahwa ArrayDeque
mungkin menjadi alternatif yang baik untuk LinkedList
untuk menambahkan dan menghapus dari kepala, tapi itu bukan Daftar
.
Juga, jika anda memiliki daftar besar, perlu diingat bahwa penggunaan memori juga berbeda. Setiap elemen dari LinkedList
memiliki lebih banyak overhead sejak pointer ke yang berikutnya dan sebelumnya juga unsur-unsur yang disimpan. ArrayLists
don't memiliki overhead. Namun, ArrayLists
memakan memori sebanyak yang dialokasikan untuk kapasitas, terlepas dari apakah unsur-unsur yang benar-benar telah ditambahkan.
Default kapasitas awal dari sebuah ArrayList
cukup kecil (10 dari Jawa 1.4 - 1.8). Tapi karena pelaksanaan yang mendasari adalah array, array harus diubah ukurannya jika anda menambahkan banyak elemen. Untuk menghindari biaya tinggi resize ketika anda tahu anda're akan menambahkan banyak elemen, membangun ArrayList
yang lebih tinggi dengan kapasitas awal.
Sejauh ini, tak seorang pun tampaknya telah membahas jejak memori dari masing-masing daftar ini selain konsensus umum bahwa LinkedList
adalah "lebih" dari sebuah ArrayList
jadi saya melakukan beberapa angka-angka untuk menunjukkan persis berapa banyak kedua daftar memakan waktu untuk N null referensi.
Sejak referensi yang baik 32 atau 64 bit (bahkan ketika null) mereka relatif sistem, saya telah menyertakan 4 set data untuk 32 dan 64 bit LinkedLists
dan ArrayLists
.
Catatan: ukuran yang ditunjukkan untuk ArrayList
garis untuk dipangkas daftar - Dalam praktek, kapasitas dukungan menginap di sebuah ArrayList
umumnya lebih besar dari elemen saat menghitung.
Catatan 2: (terima kasih BeeOnRope) Sebagai CompressedOops adalah default sekarang dari pertengahan JDK6 dan atas, nilai-nilai di bawah ini untuk mesin 64-bit pada dasarnya akan pertandingan mereka 32-bit rekan-rekan, kecuali tentu saja anda khusus mematikannya.
Hasilnya jelas menunjukkan bahwa LinkedList
adalah jauh lebih banyak dari ArrayList
, terutama yang sangat tinggi dengan elemen menghitung. Jika memori adalah sebuah faktor, steer jelas dari LinkedLists
.
Rumus yang dulu saya ikuti, biarkan aku tahu jika aku telah melakukan sesuatu yang salah dan saya akan memperbaikinya. 'b' lebih baik 4 atau 8 untuk 32 atau 64 bit sistem, dan 'n' adalah jumlah elemen. Catatan alasan untuk mods adalah karena semua benda-benda di jawa akan mengambil beberapa dari 8 byte ruang terlepas dari apakah itu semua digunakan atau tidak.
ArrayList:
ArrayList objek header + size integer + modCount integer + referensi array + (array oject header + b * n) + MOD(array oject, 8) + MOD(objek ArrayList, 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 objek header + size integer + modCount integer + referensi untuk header + referensi untuk footer + (node objek overhead + referensi ke elemen sebelumnya + referensi ke elemen berikutnya + referensi untuk elemen) * n) + MOD(node objek, 8) * n + MOD(LinkedList objek, 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)
ArrayList
adalah apa yang anda inginkan. LinkedList
hampir selalu (kinerja) bug.
Mengapa LinkedList
menyebalkan:
ArrayList
digunakan.ArrayList
, hal ini mungkin akan secara signifikan lebih lambat pula.LinkedList
di sumber karena ini mungkin adalah pilihan yang salah.Sebagai seseorang yang telah melakukan kinerja operasional teknik pada skala yang sangat besar SOA dan web services selama sekitar satu dekade, saya akan lebih memilih perilaku LinkedList lebih dari ArrayList. Sementara steady-state throughput LinkedList lebih buruk dan oleh karena itu mungkin menyebabkan untuk membeli lebih banyak hardware-perilaku ArrayList di bawah tekanan dapat menyebabkan aplikasi di cluster memperluas array di dekat sinkronisitas dan untuk array besar ukuran dapat menyebabkan kurangnya respon dalam aplikasi dan pemadaman, sementara di bawah tekanan, yang merupakan bencana besar perilaku.
Demikian pula, anda bisa mendapatkan throughput yang lebih baik dalam sebuah aplikasi dari default throughput bertenor pengumpul sampah, tetapi sekali anda mendapatkan aplikasi java dengan 10GB tumpukan anda dapat angin mengunci aplikasi selama 25 detik selama Penuh GCs yang menyebabkan timeout dan kegagalan dalam SOA aplikasi dan pukulan anda Sla jika hal ini terjadi terlalu sering. Meskipun CMS kolektor membutuhkan lebih banyak sumber daya dan tidak mencapai baku yang sama throughput, itu adalah pilihan yang jauh lebih baik karena memiliki lebih dapat diprediksi dan latency yang lebih kecil.
ArrayList adalah hanya sebuah pilihan yang lebih baik untuk kinerja jika semua yang anda maksud dengan kinerja throughput dan anda dapat mengabaikan latency. Dalam pengalaman saya di pekerjaan saya, saya tidak bisa mengabaikan kasus terburuk latency.
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)
ArrayLists yang baik untuk write-once-read-many atau appenders, tapi buruk di add/remove dari depan atau tengah.
Ya, aku tahu, ini adalah kuno pertanyaan, tapi aku'akan melempar dua sen:
LinkedList adalah hampir selalu pilihan yang salah, kinerja-bijaksana. Ada beberapa yang sangat spesifik algoritma mana yang LinkedList disebut untuk, tetapi mereka sangat, sangat langka dan algoritma biasanya akan secara khusus tergantung pada LinkedList's kemampuan untuk menyisipkan dan menghapus elemen di tengah list relatif cepat, setelah anda've navigasikan ke sana dengan ListIterator.
Ada salah satu penggunaan umum dalam kasus yang LinkedList melebihi ArrayList: bahwa antrian. Namun, jika tujuan anda adalah kinerja, bukan LinkedList anda juga harus mempertimbangkan untuk menggunakan sebuah ArrayBlockingQueue (jika anda dapat menentukan batas atas pada antrian anda ukuran dari waktu ke depan, dan mampu untuk mengalokasikan seluruh memori di depan), atau ini CircularArrayList pelaksanaan. (Ya, itu's dari tahun 2001, sehingga anda'll perlu generify itu, tapi aku punya kinerja yang sebanding rasio untuk apa's dikutip dalam artikel hanya sekarang baru JVM)
It's efisiensi pertanyaan. LinkedList
cepat untuk menambah dan menghapus elemen, tetapi lambat untuk mengakses suatu elemen tertentu. ArrayList
lebih cepat untuk mengakses suatu elemen tertentu tetapi bisa menjadi lambat untuk menambah kedua ujung, dan terutama lambat untuk menghapus di tengah.
Array vs ArrayList vs LinkedList vs Vektor pergi lebih mendalam, seperti halnya Daftar Link.
Benar atau Salah: Mohon melaksanakan tes secara lokal dan memutuskan untuk diri sendiri!
Mengedit/Menghapus lebih cepat dalam LinkedList
dari ArrayList
.
ArrayList
, yang didukung oleh Array
, yang perlu ganda ukuran, lebih buruk dalam volume besar aplikasi.
Di bawah adalah satuan hasil tes untuk setiap operasi.Waktu yang diberikan dalam Nanodetik.
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
Berikut ini's kode:
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);
}
}
ArrayList
pada dasarnya adalah sebuah array. LinkedList
ini dilaksanakan sebagai double linked list.
Dapatkan
adalah cukup jelas. O(1) untuk ArrayList
, karena ArrayList
memungkinkan akses acak dengan menggunakan indeks. O(n) untuk LinkedList
, karena itu perlu untuk menemukan indeks pertama. Catatan: ada versi yang berbeda dari add
dan hapus
.
LinkedList
lebih cepat dalam menambah dan menghapus, tapi lebih lambat dalam mendapatkan. Secara singkat, LinkedList
harus menjadi pilihan jika:
=== ArrayList ===
=== LinkedList ===
Berikut adalah gambar dari programcreek.com (add
dan menghapus
adalah jenis pertama, yaitu, menambahkan elemen pada akhir daftar dan menghapus elemen pada posisi tertentu dalam daftar.):
Joshua Bloch, penulis LinkedList:
Tidak ada yang benar-benar menggunakan LinkedList? Saya menulis itu, dan saya tidak pernah menggunakannya.
Link: https://twitter.com/joshbloch/status/583813919019573248
I'm maaf untuk jawaban yang tidak informatif sebagai jawaban yang lain, tapi saya pikir itu akan menjadi yang paling menarik dan self-explanatory.
ArrayList
yang diakses secara acak, sementara LinkedList
ini benar-benar murah untuk memperluas dan menghapus elemen dari. Untuk kebanyakan kasus, ArrayList
baik-baik saja.
Kecuali anda've dibuat daftar besar dan diukur hambatan, anda'll mungkin tidak perlu khawatir tentang perbedaan.
Jika anda memiliki kode add(0)
dan hapus(0)
, gunakan LinkedList
dan's lebih cantik addFirst()
dan removeFirst()
metode. Jika tidak, gunakan ArrayList
.
Dan tentu saja, Jambu's ImmutableList adalah teman terbaik anda.
Saya tahu ini adalah sebuah posting lama, tapi aku bisa jujur't percaya tak ada yang menyebutkan bahwa LinkedList
menerapkan Deque
. Lihat saja metode dalam Deque
(dan Antrian
); jika anda ingin perbandingan yang adil, coba jalankan LinkedList
melawan ArrayDeque
dan melakukan fitur-fitur untuk-perbandingan.
TL;DR karena komputer modern arsitektur, ArrayList
akan secara signifikan lebih efisien untuk hampir setiap kemungkinan penggunaan-kasus - dan oleh karena itu LinkedList
harus dihindari kecuali beberapa yang sangat unik dan kasus-kasus ekstrim.
Dalam teori, LinkedList memiliki O(1) untuk add(E elemen)
Juga menambahkan elemen pada pertengahan daftar harus sangat efisien.
Praktek ini sangat berbeda, sebagai LinkedList adalah Cache Bermusuhan struktur Data. Dari kinerja POV - ada sangat sedikit kasus-kasus di mana LinkedList
bisa berkinerja lebih baik daripada Cache-friendly ArrayList
.
Berikut ini adalah hasil pengujian benchmark memasukkan unsur-unsur di lokasi secara acak. Seperti yang anda lihat - daftar array jika jauh lebih efisien, meskipun dalam teori masing-masing menyisipkan di tengah-tengah daftar akan membutuhkan "pindah" n kemudian elemen array (nilai lebih rendah lebih baik):
Bekerja pada generasi berikutnya perangkat keras (lebih besar, lebih efisien cache) - hasil yang bahkan lebih konklusif:
LinkedList membutuhkan waktu lebih banyak untuk menyelesaikan pekerjaan yang sama. source Source Code
Ada dua alasan utama untuk ini:
Terutama - bahwa node LinkedList
yang tersebar secara acak di memori. RAM ("Random Access Memory") isn't benar-benar acak dan blok memori yang perlu diambil untuk cache. Operasi ini membutuhkan waktu, dan ketika menjemput sering terjadi - halaman memori di cache perlu diganti semua waktu -> Cache misses -> Cache tidak efisien.
ArrayList
unsur-unsur yang disimpan terus menerus memori - yang persis apa yang modern arsitektur CPU adalah mengoptimalkan.
Sekunder LinkedList
yang diperlukan untuk menahan/pointer ke depan, yang berarti 3 kali pemakaian memori per nilai yang disimpan dibandingkan dengan ArrayList
.
DynamicIntArray, btw, kebiasaan ArrayList pelaksanaan memegang Int
(primitive type) dan bukan Benda - maka semua data benar-benar disimpan pendampingan - maka lebih efisien.
Sebuah elemen kunci yang perlu diingat adalah bahwa biaya pengambilan blok memori, lebih signifikan dari pada biaya mengakses satu sel memori. Yang's mengapa pembaca 1MB berurutan memori hingga x400 kali lebih cepat dari membaca ini jumlah data dari blok yang berbeda dari memori:
Latency Comparison Numbers (~2012)
----------------------------------
L1 cache reference 0.5 ns
Branch mispredict 5 ns
L2 cache reference 7 ns 14x L1 cache
Mutex lock/unlock 25 ns
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy 3,000 ns 3 us
Send 1K bytes over 1 Gbps network 10,000 ns 10 us
Read 4K randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
Read 1 MB sequentially from memory 250,000 ns 250 us
Round trip within same datacenter 500,000 ns 500 us
Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory
Disk seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip
Read 1 MB sequentially from disk 20,000,000 ns 20,000 us 20 ms 80x memory, 20X SSD
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
Sumber: Latency Angka Setiap Programmer Harus Tahu
Hanya untuk membuat titik bahkan lebih jelas, silahkan periksa acuan untuk menambahkan elemen ke awal daftar. Ini adalah penggunaan-kasus di mana, dalam teori, LinkedList
harus benar-benar bersinar, dan ArrayList
harus hadir miskin atau bahkan lebih buruk-kasus hasil:
Catatan: ini adalah acuan dari C++ Std lib, tapi pengalaman saya sebelumnya yang ditunjukkan dengan C++ dan Java hasil yang sangat mirip. Source Code
Menyalin berurutan massal memori merupakan operasi yang dioptimalkan oleh Cpu modern - mengubah teori dan benar-benar membuat, sekali lagi, ArrayList
/Vektor
jauh lebih efisien
Credits: Semua tolok ukur yang diposting di sini adalah yang dibuat oleh Kjell Hedström. Bahkan lebih banyak data yang dapat ditemukan di blog
Berikut ini adalah Big-O notasi dalam kedua ArrayList
dan LinkedList
dan juga 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-ArrayList
get O(1)
add O(n)
contains O(n)
next O(1)
remove O(n)
iterator.remove O(n)
Berdasarkan ini, anda harus memutuskan apa yang harus dipilih. :)
Let's membandingkan LinkedList dan ArrayList w.r.t. berikut parameter:
ArrayList adalah resizable array pelaksanaan daftar interface , sedangkan
LinkedList adalah Doubly-linked list pelaksanaan daftar antarmuka.
ArrayList get(int index) operasi yang berjalan dalam waktu yang konstan saya.e O(1) sementara
LinkedList get(int index) operasi berjalan waktu adalah O(n) .
Alasan di balik ArrayList menjadi lebih cepat dari LinkedList adalah bahwa ArrayList menggunakan indeks berdasarkan sistem untuk unsur-unsur seperti ini secara internal menggunakan sebuah array struktur data, di sisi lain,
LinkedList tidak memberikan indeks berbasis akses untuk unsur-unsur seperti itu iterates baik dari awal atau akhir (mana yang lebih dekat) untuk mengambil node pada yang ditentukan elemen indeks.
Sisipan dalam LinkedList umumnya cepat dibandingkan dengan ArrayList. Di LinkedList penambahan atau penyisipan adalah O(1) operasi .
Sementara di ArrayList, jika array penuh saya.e kasus terburuk, ada tambahan biaya mengubah ukuran array dan menyalin elemen ke array baru, yang membuat runtime menambahkan operasi dalam ArrayList O(n), jika tidak, itu adalah O(1).
Menghapus operasi dalam LinkedList ini umumnya sama seperti ArrayList yaitu O(n).
Di LinkedList, ada dua kelebihan beban menghapus metode. salah satunya adalah menghapus() tanpa parameter apapun yang menghilangkan kepala daftar dan berjalan dalam waktu yang konstan O(1). Lainnya kelebihan beban menghapus metode dalam LinkedList adalah menghapus(int) atau menghapus(Objek) yang menghapus Objek atau int dilewatkan sebagai parameter. Metode ini melintasi LinkedList sampai ditemukan Objek dan memutuskannya dari daftar asli. Oleh karena itu metode ini runtime adalah O(n).
Sementara di ArrayList remove(int) metode ini melibatkan menyalin elemen dari array yang lama ke yang baru diperbarui array, maka runtime nya adalah O(n).
LinkedList dapat iterasi ke arah sebaliknya menggunakan descendingIterator() sementara
tidak ada descendingIterator() in ArrayList , jadi kita perlu menulis kode kita sendiri untuk iterate atas ArrayList ke arah sebaliknya.
Jika konstruktor tidak kelebihan beban, maka ArrayList membuat daftar kosong dari kapasitas awal 10, sementara
LinkedList hanya membangun daftar kosong tanpa kapasitas awal.
Memori overhead dalam LinkedList lebih dibandingkan dengan ArrayList sebagai sebuah simpul dalam LinkedList kebutuhan untuk mempertahankan alamat berikutnya dan sebelumnya node. Sementara
Di ArrayList indeks masing-masing hanya memegang objek yang sebenarnya(data).
Saya biasanya menggunakan salah satu dari yang lain berdasarkan waktu kompleksitas operasi yang saya'd tampil di Daftar khusus tersebut.
|---------------------|---------------------|--------------------|------------|
| Operation | ArrayList | LinkedList | Winner |
|---------------------|---------------------|--------------------|------------|
| get(index) | O(1) | O(n) | ArrayList |
| | | n/4 steps in avg | |
|---------------------|---------------------|--------------------|------------|
| add(E) | O(1) | O(1) | LinkedList |
| |---------------------|--------------------| |
| | O(n) in worst case | | |
|---------------------|---------------------|--------------------|------------|
| add(index, E) | O(n) | O(n) | LinkedList |
| | n/2 steps | n/4 steps | |
| |---------------------|--------------------| |
| | | O(1) if index = 0 | |
|---------------------|---------------------|--------------------|------------|
| remove(index, E) | O(n) | O(n) | LinkedList |
| |---------------------|--------------------| |
| | n/2 steps | n/4 steps | |
|---------------------|---------------------|--------------------|------------|
| Iterator.remove() | O(n) | O(1) | LinkedList |
| ListIterator.add() | | | |
|---------------------|---------------------|--------------------|------------|
|--------------------------------------|-----------------------------------|
| ArrayList | LinkedList |
|--------------------------------------|-----------------------------------|
| Allows fast read access | Retrieving element takes O(n) |
|--------------------------------------|-----------------------------------|
| Adding an element require shifting | o(1) [but traversing takes time] |
| all the later elements | |
|--------------------------------------|-----------------------------------|
| To add more elements than capacity |
| new array need to be allocated |
|--------------------------------------|
Selain baik argumen-argumen di atas, anda harus melihat ArrayList
menerapkan RandomAccess
antarmuka, sementara LinkedList
menerapkan Antrian
.
Jadi, entah bagaimana mereka mengatasi sedikit masalah yang berbeda, dengan perbedaan efisiensi dan perilaku (melihat daftar metode).
Hal ini tergantung pada operasi apa yang anda akan lakukan lebih pada Daftar.
ArrayList
lebih cepat untuk mengakses nilai yang diindeks. Hal ini jauh lebih buruk ketika memasukkan atau menghapus objek.
Untuk mengetahui lebih lanjut, baca artikel yang berbicara tentang perbedaan antara array dan linked list.