2011-01-25 10 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) 

Inne niż użycie next, hasNext, kiedy powinienem wybrać iterator na widok lub przeglądać iterator?Jaka jest różnica między metodami iteratora i widoku?

Odpowiedz

36

Istnieje ogromna różnica między iteratorami i widokami. Iteratory są używane tylko jeden raz, obliczane na żądanie, podczas gdy widoki są używane wielokrotnie, przeliczaj za każdym razem, ale tylko potrzebne elementy. Na przykład:

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 produkuje leniwe zbiórki/strumień. Jego głównym urokiem jest to, że nie będzie starał się zbudować całej kolekcji. Może to zapobiec OutOfMemoryError lub poprawić wydajność, gdy potrzebujesz tylko kilku pierwszych elementów w kolekcji. iterator nie daje takiej gwarancji.

Jeszcze jedno. Przynajmniej na Range, view zwraca SeqView, który jest podtypem Seq, więc można wrócić i zacząć od początku i zrobić wszystko, sequency zabawne rzeczy.

Myślę, że różnica między iteratora i widok jest kwestią w przód i tył. Iteratory powinny wypuścić to, co widzieliśmy. Po wywołaniu next poprzednie, mam nadzieję, puścić. Widoki są odwrotnością. Obiecują, że nie zdobędą tego, czego nie zażądano. Jeśli masz widok wszystkich liczb pierwszych, zbiór nieskończony, uzyskał tylko te liczby pierwsze, o które prosiłeś. Chcieliście, żeby 100, 101 jeszcze nie zajęło się pamięcią.

+0

Zobacz Iterator # map, tworzy nowy iterator, który leniwie ocenia funkcję przekazaną do mapy dla każdego "następnego". Wygląda więc na to, że wygląda dokładnie tak, jak w widoku – IttayD

+3

@Ittay: True, ale tego nie ma w umowie. Iteractor obiecuje "następną metodę, która zwraca następny element i odrzuca go z iteratora". Podczas gdy IterableView obiecuje być "nie surowym". – sblundy

0

Ta page mówi o tym, kiedy używać widoków.

Podsumowując, widoki są potężnym narzędziem do pogodzenia obaw wydajności z obawy modułowości. Aby jednak nie być uwikłanym w aspekty opóźnionej oceny, należy ograniczyć widoki do dwóch scenariuszy. Albo zastosujesz widoki w czysto funkcjonalnym kodzie , gdzie transformacje kolekcji nie mają skutków ubocznych. Albo Ty, , zastosuj je do zmiennego zbioru, w którym wszystkie modyfikacje są jawnie wykonane . Najlepszym rozwiązaniem jest połączenie widoków i operacji, które tworzą nowe kolekcje, a jednocześnie mają efekty uboczne.

Powiązane problemy