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

Además de utilizar next, hasNext, ¿cuándo debería elegir iterator over view o view over iterator?¿Cuál es la diferencia entre los métodos iterator y view?

Respuesta

36

Hay una gran diferencia entre los iteradores y las vistas. Los iteradores se usan una sola vez, se calculan según demanda, mientras que las vistas se usan varias veces, vuelven a calcular cada vez, pero solo los elementos necesarios. Por ejemplo:

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 produce una colección/secuencia diferida. Su principal encanto es que no intentará construir toda la colección. Esto podría evitar un OutOfMemoryError o mejorar el rendimiento cuando solo necesita los primeros elementos de la colección. iterator no hace tal garantía.

Una cosa más. Al menos en Range, view devuelve SeqView, que es un subtipo de Seq, por lo que puede volver atrás o comenzar de nuevo desde el principio y hacer todas esas cosas divertidas de secuencia.

Supongo que la diferencia entre un iterador y una vista es una cuestión de frente y detrás. Se espera que los iteradores divulguen lo que se ha visto. Una vez que se ha llamado al next, el anterior es, con suerte, soltado. Las vistas son lo contrario. Prometen no adquirir lo que no se ha solicitado. Si tiene una vista de todos los números primos, un conjunto infinito, solo ha adquirido los números primos que ha solicitado. Si quisieras el centésimo, 101 no debería tomar memoria todavía.

+0

Ver Iterator # map, crea un nuevo iterador que evalúa perezosamente la función pasada al mapa para cada 'siguiente'. Por lo tanto, parece actuar exactamente como una vista – IttayD

+3

@Ittay: Es cierto, pero eso no está en el contrato. Iteractor promete el siguiente método que devuelve el siguiente elemento y lo descarta del iterador. Mientras que las promesas de IterableView son 'no estrictas'. – sblundy

0

Este page habla sobre cuándo utilizar puntos de vista.

En resumen, las vistas son una poderosa herramienta para conciliar las preocupaciones de la eficiencia con las preocupaciones de la modularidad. Pero para no ser enredado en aspectos de la evaluación diferida, debe restringir las vistas a dos escenarios. O bien, aplica vistas en el código funcional , donde las transformaciones de recopilación no tienen efectos secundarios. O bien, los aplica sobre colecciones mutables donde todas las modificaciones se realizan explícitamente. Lo mejor que se debe evitar es una combinación de vistas y operaciones que crean nuevas colecciones y, al mismo tiempo, tienen efectos secundarios.

Cuestiones relacionadas