TL; DR karena arsitektur komputer modern, ArrayList
akan jauh lebih efisien untuk hampir semua kasus penggunaan yang mungkin - dan karenanya LinkedList
harus dihindari kecuali beberapa kasus yang sangat unik dan ekstrem.
Secara teori, LinkedList memiliki O (1) untuk add(E element)
Juga menambahkan elemen di tengah daftar harus sangat efisien.
Praktiknya sangat berbeda, karena LinkedList adalah struktur Data Cache Hostile . Dari kinerja POV - ada sedikit kasus di mana LinkedList
bisa lebih baik daripada Cache-friendly ArrayList
.
Berikut adalah hasil dari elemen penyisipan pengujian patokan di lokasi acak. Seperti yang Anda lihat - daftar array jika jauh lebih efisien, meskipun dalam teori setiap insert di tengah daftar akan membutuhkan "pindahkan" elemen n kemudian array (nilai yang lebih rendah lebih baik):
Bekerja pada perangkat keras generasi selanjutnya (cache yang lebih besar, lebih efisien) - hasilnya bahkan lebih konklusif:
LinkedList membutuhkan lebih banyak waktu untuk menyelesaikan pekerjaan yang sama. kode sumber sumber
Ada dua alasan utama untuk ini:
Terutama - bahwa node LinkedList
tersebar secara acak di memori. RAM ("Random Access Memory") tidak benar-benar acak dan blok memori perlu diambil ke cache. Operasi ini membutuhkan waktu, dan ketika pengambilan itu sering terjadi - halaman memori dalam cache harus diganti setiap saat -> Cache misses -> Cache tidak efisien.
ArrayList
elemen disimpan pada memori terus menerus - itulah yang dioptimalkan oleh arsitektur CPU modern.
Sekunder LinkedList
diperlukan untuk menahan pointer maju / mundur, yang berarti 3 kali pemakaian memori per nilai yang disimpan dibandingkan dengan ArrayList
.
DynamicIntArray , btw, adalah implementasi implementasi ArrayList kustom Int
(tipe primitif) dan bukan Objects - maka semua data benar-benar disimpan secara bersebelahan - karenanya bahkan lebih efisien.
Elemen kunci yang perlu diingat adalah bahwa biaya mengambil blok memori, lebih signifikan daripada biaya mengakses sel memori tunggal. Itu sebabnya pembaca 1MB memori sekuensial hingga x400 kali lebih cepat daripada membaca jumlah data ini dari berbagai blok 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: Nomor Latensi yang Harus Diketahui Setiap Programmer
Agar poinnya lebih jelas, silakan periksa tolok ukur penambahan elemen di awal daftar. Ini adalah kasus penggunaan di mana, dalam teori, LinkedList
harus benar-benar bersinar, dan ArrayList
harus menyajikan hasil kasus yang buruk atau bahkan lebih buruk:
Catatan: ini adalah tolok ukur dari C ++ Std lib, tetapi pengalaman saya sebelumnya menunjukkan hasil C ++ dan Java sangat mirip. Kode sumber
Menyalin sebagian besar memori adalah operasi yang dioptimalkan oleh CPU modern - mengubah teori dan benar-benar membuat, sekali lagi, ArrayList
/ Vector
jauh lebih efisien
Kredit: Semua tolok ukur yang diposting di sini dibuat oleh Kjell Hedström . Bahkan lebih banyak data dapat ditemukan di blog-nya