Perbedaan antara Array dan Daftar di scala

142

Dalam kasus apa saya harus menggunakan Array (Buffer) dan List (Buffer). Hanya satu perbedaan yang saya tahu adalah bahwa array adalah bukan varian dan daftar adalah kovarian. Tetapi bagaimana dengan kinerja dan beberapa karakteristik lainnya?

Jeriho
sumber

Jawaban:

155

Struktur Kekal

Scala Listadalah struktur data rekursif berubah yang adalah suatu struktur fundamental dalam Scala, bahwa Anda harus (mungkin) akan menggunakannya lebih dari satu Array(yang sebenarnya bisa berubah - yang analog berubah dari Arrayyang IndexedSeq).

Jika Anda berasal dari latar belakang Jawa, maka paralel yang jelas adalah ketika menggunakan LinkedListlebih ArrayList. Yang pertama umumnya digunakan untuk daftar yang hanya pernah dilintasi (dan yang ukurannya tidak diketahui dimuka) sedangkan yang kedua harus digunakan untuk daftar yang memiliki ukuran yang diketahui (atau ukuran maksimum) atau yang penting untuk akses acak cepat .

Struktur yang Dapat Berubah

ListBuffermemberikan konversi waktu-konstan ke Listyang hanya digunakan untuk alasan ListBufferjika diperlukan konversi nanti.

Scala Arrayharus diimplementasikan pada JVM oleh array Java, dan karenanya Array[Int]mungkin lebih performan (sebagai int[]) dari List[Int](yang akan mengotak isinya, kecuali Anda menggunakan versi Scala terbaru yang memiliki @specializedfitur baru ) .

Namun, saya berpikir bahwa penggunaan Arrays di Scala harus dijaga agar tetap minimum karena rasanya Anda benar-benar perlu tahu apa yang terjadi di bawah tenda untuk memutuskan apakah array Anda benar-benar akan didukung oleh tipe primitif yang diperlukan, atau mungkin kotak sebagai jenis pembungkus.

oxbow_lakes
sumber
juga lihat stackoverflow.com/questions/3213368/… dan stackoverflow.com/questions/2481149/... definisi "sama dengan" untuk Array adalah bahwa mereka merujuk ke array yang sama
oluies
130

Selain jawaban yang sudah diposting, berikut adalah beberapa spesifik.

Sementara Array[A]secara harfiah array Java, sebuah List[A]adalah struktur data berubah yang baik Nil(daftar kosong) atau terdiri dari sepasang (A, List[A]).

Perbedaan kinerja

                          Array  List
Access the ith element    θ(1)   θ(i)
Delete the ith element    θ(n)   θ(i)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)
Count the elements        θ(1)   θ(n)

Perbedaan memori

                          Array  List
Get the first i elements  θ(i)   θ(i)
Drop the first i elements θ(n-i) θ(1)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)

Jadi, kecuali Anda memerlukan akses acak cepat, perlu menghitung elemen, atau karena alasan tertentu Anda memerlukan pembaruan yang merusak, a Listlebih baik daripada a Array.

Apocalisp
sumber
Apakah O ini harus mempertimbangkan waktu untuk menyalin Daftar? Saya berasumsi Anda melakukan tes seperti ini, misalnya: list = list.drop(i). Atau, Apakah ada keajaiban di balik tudung?
2
Ini memperhitungkan daftar dan array penyalinan akun bila perlu. Perhatikan bahwa hal-hal seperti droptidak perlu menyalin bagian dari daftar yang tidak dibatalkan. Misalnya (x::xs).drop(1)persis xs, bukan "salinan" dari xs.
Apocalisp
6
Asimptotik ini tidak ada hubungannya dengan Scala sama sekali. Struktur data yang sama dalam C akan sama cepatnya dengan faktor-faktor konstan.
Apocalisp
1
@Apocalisp Apakah Anda memiliki referensi atau dalam kondisi apa Anda menentukan informasi ini?
Phil
1
@ Phil Ini adalah asimptotik, bukan pengukuran. Mereka akan berlaku di semua kondisi.
Apocalisp
18

Array bisa berubah, artinya Anda dapat mengubah nilai setiap indeks, sedangkan Daftar (secara default) tidak berubah, artinya daftar baru dibuat setiap kali Anda melakukan modifikasi. Dalam kebanyakan kasus itu adalah lebih "fungsional" gaya bekerja dengan tipe data berubah dan Anda mungkin harus mencoba dan menggunakan Daftar dengan konstruksi seperti yield, foreach, matchdan sebagainya.

Untuk karakteristik kinerja, sebuah Array lebih cepat dengan akses acak ke elemen, sedangkan Daftar lebih cepat ketika menambahkan (menambahkan) elemen baru. Iterasi atas mereka sebanding.

leonm
sumber
@leonm - apol, saya pikir OP bertanya secara eksklusif tentang kelas * Buffer, saya menyadari bahwa mereka juga bertanya tentang yang "normal"!
oxbow_lakes
2
Biasanya lebih cepat untuk menambahkan ke ArrayBuffer daripada prepend ke Daftar (atau menambahkan elemen ke ListBuffer) karena daftar memerlukan pembuatan objek pembungkus sementara ArrayBuffer hanya perlu menyalin objek (rata-rata sekitar dua kali) ke array baru . Dua salinan biasanya lebih cepat dari satu pembuatan objek, jadi ArrayBuffer append biasanya mengalahkan Daftar prepend.
Rex Kerr
array melakukan jauh lebih cepat daripada daftar ketika iterate over, karena cache
Bin