Streaming vs Tampilan vs Iterator

136

Apa perbedaan antara Stream, Views (SeqView), dan Iterator dalam skala? Inilah pemahaman saya:

  • Mereka semua adalah daftar malas.
  • Aliran menyimpan nilai di cache.
  • Iterator hanya dapat digunakan sekali? Anda tidak dapat kembali ke awal dan mengevaluasi nilainya lagi?
  • Nilai tampilan tidak disimpan dalam cache tetapi Anda dapat mengevaluasinya lagi dan lagi?

Jadi jika saya ingin menghemat ruang heap, haruskah saya menggunakan iterator (jika saya tidak akan menelusuri daftar lagi) atau tampilan? Terima kasih.

JWC
sumber
7
Saya telah menjawab ini sebelumnya, tetapi bagaimana menemukannya? menghela napas ...
Daniel C. Sobral

Jawaban:

183

Pertama, mereka semua tidak ketat . Itu memiliki arti matematis tertentu yang terkait dengan fungsi, tetapi, pada dasarnya, berarti fungsi tersebut dihitung sesuai permintaan, bukan sebelumnya.

Streammemang daftar malas. Bahkan, di Scala, sebuah Streamadalah Listyang tailadalah lazy val. Setelah dihitung, sebuah nilai tetap dihitung dan digunakan kembali. Atau, seperti yang Anda katakan, nilainya di-cache.

An Iteratorhanya dapat digunakan sekali karena ini adalah penunjuk traversal ke dalam koleksi, dan bukan koleksi itu sendiri. Apa yang membuatnya istimewa di Scala adalah kenyataan bahwa Anda dapat menerapkan transformasi seperti mapdan filterdan hanya mendapatkan yang baru Iteratoryang hanya akan menerapkan transformasi ini ketika Anda meminta elemen berikutnya.

Scala dulu menyediakan iterator yang dapat disetel ulang, tetapi sangat sulit untuk didukung secara umum, dan mereka tidak membuat versi 2.8.0.

Tampilan dimaksudkan untuk dilihat seperti tampilan database. Ini adalah rangkaian transformasi yang diterapkan pada suatu koleksi untuk menghasilkan koleksi "virtual". Seperti yang Anda katakan, semua transformasi diterapkan kembali setiap kali Anda perlu mengambil elemen darinya.

Baik Iteratortampilan maupun tampilan memiliki karakteristik memori yang sangat baik. Streambagus, tetapi, di Scala, manfaat utamanya adalah menulis urutan tak terbatas (terutama urutan yang didefinisikan secara rekursif). Seseorang dapat menghindari menyimpan semua Streamdalam memori, dengan memastikan Anda tidak menyimpan referensi ke its head(misalnya, dengan menggunakan defalih-alih valmendefinisikan Stream).

Karena penalti yang ditimbulkan oleh tampilan, seseorang harus forcemenggunakannya setelah menerapkan transformasi, atau menyimpannya sebagai tampilan jika hanya beberapa elemen yang diharapkan akan diambil, dibandingkan dengan ukuran total tampilan.

Daniel C. Sobral
sumber
10
Iteratorjuga cukup berguna untuk menyelidiki yang tak terbatas, dan saya biasanya lebih memilihnya daripada aliran jika memungkinkan. Manfaat nyata dalam aliran adalah bahwa nilai yang diakses sebelumnya disimpan dalam cache, yang merupakan keuntungan serius saat mencoba menerapkan sesuatu seperti urutan fibonacci - yang didefinisikan dalam istilah nilai sebelumnya.
Kevin Wright
5
Fibonacci adalah contoh yang kurang sempurna karena hanya membutuhkan 2 nilai terakhir sebelumnya, dan menjaga keseluruhan aliran adalah pemborosan. Fungsi Ackermann mungkin adalah contoh kanonik.
Jürgen Strobel
4
@ JürgenStrobel Ackermann akan menghasilkan kinerja yang buruk, karena akses aliran yang diindeks adalah O (n). Tapi saya setuju dengan fibonacci.
Daniel C. Sobral
9
Oh iya. Hal ini membuat Stream menjadi pilihan yang buruk untuk pendekatan caching apa pun.
Jürgen Strobel
7
Jawaban ini sangat jelas, seharusnya menjadi bagian dari dokumentasi ... oh, sebenarnya begitu! Terima kasih Daniel docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Svend