Truyền phát vs Lượt xem vs Trình lặp


136

Sự khác biệt giữa Luồng, Lượt xem (SeqView) và Trình lặp trong scala là gì? Đây là sự hiểu biết của tôi:

  • Họ đều là những danh sách lười biếng.
  • Luồng lưu trữ các giá trị.
  • Lặp lại chỉ có thể được sử dụng một lần? Bạn không thể quay lại từ đầu và đánh giá lại giá trị?
  • Giá trị của view không được lưu trong bộ nhớ cache nhưng bạn có thể đánh giá chúng nhiều lần không?

Vì vậy, nếu tôi muốn tiết kiệm không gian heap, tôi nên sử dụng các trình vòng lặp (nếu tôi sẽ không duyệt qua danh sách một lần nữa) hoặc các chế độ xem? Cảm ơn.


7
Tôi đã trả lời điều này trước đây, nhưng làm thế nào để tìm thấy nó? thở dài ...
Daniel C. Sobral

Câu trả lời:


182

Đầu tiên, tất cả đều không nghiêm ngặt . Điều đó có một ý nghĩa toán học cụ thể liên quan đến các hàm, nhưng, về cơ bản, có nghĩa là chúng được tính toán theo yêu cầu thay vì trước.

Streamlà một danh sách lười biếng thực sự. Trong thực tế, ở Scala, a Streamlà một Listngười có taila lazy val. Sau khi tính toán, một giá trị vẫn được tính toán và được sử dụng lại. Hoặc, như bạn nói, các giá trị được lưu trữ.

An Iteratorchỉ có thể được sử dụng một lần vì nó là con trỏ truyền tải vào bộ sưu tập chứ không phải là bộ sưu tập. Điều gì làm cho nó đặc biệt trong Scala là một thực tế mà bạn có thể áp dụng chuyển đổi như mapfiltervà chỉ cần có được một mới Iteratorsẽ chỉ áp dụng những biến đổi khi bạn yêu cầu các phần tử tiếp theo.

Scala đã từng cung cấp các trình vòng lặp có thể được đặt lại, nhưng điều đó rất khó để hỗ trợ một cách chung chung và họ đã không tạo ra phiên bản 2.8.0.

Lượt xem có nghĩa là được xem giống như chế độ xem cơ sở dữ liệu. Đó là một loạt các phép biến đổi áp dụng cho bộ sưu tập để tạo ra bộ sưu tập "ảo". Như bạn đã nói, tất cả các phép biến đổi được áp dụng lại mỗi lần bạn cần tìm nạp các phần tử từ nó.

Cả hai Iteratorvà quan điểm có đặc điểm bộ nhớ tuyệt vời. Streamlà tốt, nhưng, trong Scala, lợi ích chính của nó là viết các chuỗi vô hạn (đặc biệt là các chuỗi được định nghĩa đệ quy). Tuy nhiên, người ta có thể tránh giữ tất cả Streambộ nhớ trong bằng cách đảm bảo rằng bạn không giữ một tham chiếu đến nó head(ví dụ: bằng cách sử dụng defthay vì valđể xác định Stream).

Do các hình phạt phát sinh bởi các chế độ xem, người ta thường nên xử lý forcenó sau khi áp dụng các biến đổi hoặc giữ nó làm chế độ xem nếu chỉ có một số yếu tố được mong đợi được tìm nạp, so với tổng kích thước của chế độ xem.


10
Iteratorcũng khá thuận tiện để thăm dò vô hạn, và tôi thường thích chúng hơn các luồng nếu có thể. Lợi ích thực sự trong các luồng là các giá trị được truy cập trước đó được lưu trong bộ nhớ cache, đây là một lợi ích nghiêm trọng khi cố gắng thực hiện một cái gì đó giống như chuỗi Wikipedia - được định nghĩa theo các giá trị trước đó.
Kevin Wright

5
Fibonacci là một ví dụ ít hoàn hảo hơn vì nó chỉ cần 2 giá trị trước đó và việc giữ toàn bộ luồng là một sự lãng phí. Hàm Ackermann có lẽ là ví dụ điển hình.
Jürgen Strobel

4
@ JürgenStrobel Ackermann sẽ dẫn đến hiệu suất tệ hại, vì truy cập được lập chỉ mục của các luồng là O (n). Nhưng tôi đồng ý wrt Dailymotion.
Daniel C. Sobral

9
Ô đúng rồi. Điều này làm cho Stream trở thành một lựa chọn kém cho bất kỳ phương pháp lưu trữ.
Jürgen Strobel

7
Câu trả lời này là rất rõ ràng, nó nên là một phần của tài liệu ... oh, thực sự nó là vậy! Cảm ơn Daniel docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Svend
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.