2011-01-25 64 views
29
scala> (1 to 10).iterator.map{_ * 2}.toList 
res1: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) 

scala> (1 to 10).view.map{_ * 2}.force 
res2: Seq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) 

Khác với việc sử dụng tiếp theo, hasNext, khi nào tôi nên chọn trình lặp qua chế độ xem hoặc xem qua trình lặp?Sự khác biệt giữa các phương thức lặp và xem là gì?

Trả lời

36

Có sự khác biệt lớn giữa các trình vòng lặp và chế độ xem. Iterator chỉ được sử dụng một lần, tính toán theo yêu cầu, trong khi chế độ xem được sử dụng nhiều lần, tính toán lại mỗi lần, nhưng chỉ các phần tử cần thiết. Ví dụ:

scala> val list = List(1,2,3).map{x => println(x); x * 2} 
1 
2 
3 
list: List[Int] = List(2, 4, 6) 

scala> list(2) 
res14: Int = 6 

scala> list(2) 
res15: Int = 6 

scala> val view = List(1,2,3).view.map{x => println(x); x * 2} 
view: scala.collection.SeqView[Int,Seq[_]] = SeqViewM(...) 

scala> view(2) 
3 
res12: Int = 6 

scala> view(2) 
3 
res13: Int = 6 

scala> val iterator = List(1,2,3).iterator.map{x => println(x); x * 2} 
iterator: Iterator[Int] = non-empty iterator 

scala> iterator.drop(2).next 
1 
2 
3 
res16: Int = 6 

scala> iterator.drop(2).next 
[Iterator.next] (Iterator.scala:29) 
(access lastException for the full trace) 
20

view tạo bộ sưu tập/luồng lười biếng. Đó là sự quyến rũ chính là nó sẽ không cố gắng và xây dựng toàn bộ bộ sưu tập. Điều này có thể ngăn chặn lỗi OutOfMemoryError hoặc cải thiện hiệu suất khi bạn chỉ cần một vài mục đầu tiên trong bộ sưu tập. iterator không đảm bảo như vậy.

Một điều nữa. Ít nhất là trên Range, view trả về một SeqView, là loại phụ của Seq, vì vậy bạn có thể quay lại hoặc bắt đầu lại từ đầu và làm tất cả những thứ liên tiếp thú vị đó.

Tôi đoán sự khác biệt giữa trình lặp và chế độ xem là vấn đề ở phía trước và phía sau. Iterator dự kiến ​​sẽ phát hành những gì đã được nhìn thấy. Sau khi next được gọi, trước đó là, hy vọng, hãy buông bỏ. Lượt xem là trò chuyện. Họ hứa sẽ không có được những gì chưa được yêu cầu. Nếu bạn có một cái nhìn của tất cả các số nguyên tố, một tập hợp vô hạn, nó chỉ có được những số nguyên tố bạn đã yêu cầu. Bạn muốn có 100, 101 không nên chiếm bộ nhớ.

+0

Xem Iterator # map, nó tạo một trình lặp mới để đánh giá một cách lười biếng chức năng được truyền tới bản đồ cho từng 'tiếp theo'. Vì vậy, nó có vẻ hành động chính xác như một cái nhìn – IttayD

+3

@ Ittay: Đúng, nhưng đó không phải là trong hợp đồng. Iteractor hứa hẹn 'phương thức tiếp theo trả về phần tử tiếp theo và loại bỏ nó khỏi trình lặp.' Trong khi IterableView hứa hẹn là 'không nghiêm ngặt'. – sblundy

0

page nói về thời điểm sử dụng chế độ xem.

Tóm lại, lượt xem là công cụ mạnh mẽ để điều chỉnh mối quan tâm của hiệu suất mô đun. Nhưng để không bị vướng vào các khía cạnh của việc đánh giá bị trì hoãn, bạn nên hạn chế chế độ xem thành hai trường hợp. Hoặc bạn áp dụng chế độ xem theo mã chức năng thuần túy trong đó các phép biến đổi bộ sưu tập không có tác dụng phụ. Hoặc bạn áp dụng chúng trên các bộ sưu tập có thể thay đổi khi tất cả các sửa đổi được thực hiện một cách rõ ràng. Cách tốt nhất nên tránh là một hỗn hợp các quan điểm và hoạt động tạo ra các bộ sưu tập mới trong khi cũng có các phản ứng phụ.

Các vấn đề liên quan