En resumen: un Iterator
tiene estado, mientras que un Iterable
no.
Consulte los documentos de la API para ambos.
Iterable:
Un rasgo base para colecciones iterables.
Este es un rasgo básico para todas las colecciones de Scala que definen un método de iterador para recorrer uno a uno los elementos de la colección. [...] Este rasgo implementa el método foreach de Iterable al recorrer a través de todos los elementos usando el iterador.
Iterator:
iteradores son estructuras de datos que permiten a iterar sobre una secuencia de elementos. Tienen un método hasNext para comprobar si hay un próximo elemento disponible, y un siguiente método que devuelve el siguiente elemento y lo descarta del iterador.
Un iterador es mutable: la mayoría de las operaciones en él cambian su estado. Mientras que se usa a menudo para iterar a través de los elementos de una colección, también se puede usar sin estar respaldado por ninguna colección (vea constructores en el objeto complementario).
Con un Iterator
puede detener una iteración y continuarla más tarde si lo desea. Si intenta hacer esto con un Iterable
que comenzará a partir de la cabeza de nuevo:
scala> val iterable: Iterable[Int] = 1 to 4
iterable: Iterable[Int] = Range(1, 2, 3, 4)
scala> iterable.take(2)
res8: Iterable[Int] = Range(1, 2)
scala> iterable.take(2)
res9: Iterable[Int] = Range(1, 2)
scala> val iterator = iterable.iterator
iterator: Iterator[Int] = non-empty iterator
scala> if (iterator.hasNext) iterator.next
res23: AnyVal = 1
scala> if (iterator.hasNext) iterator.next
res24: AnyVal = 2
scala> if (iterator.hasNext) iterator.next
res25: AnyVal = 3
scala> if (iterator.hasNext) iterator.next
res26: AnyVal = 4
scala> if (iterator.hasNext) iterator.next
res27: AnyVal =()
Tenga en cuenta, que yo no uso take
en Iterator
. La razón de esto es que es difícil de usar. hasNext
y next
son los únicos dos métodos que están garantizados para funcionar como se espera en Iterator
.Véase el nuevo Scaladoc:
Es de particular importancia tener en cuenta que, a menos que se indique lo contrario, uno nunca debe utilizar un iterador después de llamar a un método en él. Las dos excepciones más importantes de son también los únicos métodos abstractos: next y hasNext.
Ambos métodos se pueden llamar cualquier cantidad de veces sin tener que descartar el iterador. Tenga en cuenta que incluso hasNext puede causar la mutación - , por ejemplo, al iterar desde un flujo de entrada, donde bloqueará hasta , la transmisión se cerrará o habrá alguna entrada disponible.
Considere este ejemplo para el uso seguro e inseguro:
def f[A](it: Iterator[A]) = {
if (it.hasNext) { // Safe to reuse "it" after "hasNext"
it.next // Safe to reuse "it" after "next"
val remainder = it.drop(2) // it is *not* safe to use "it" again after this line!
remainder.take(2) // it is *not* safe to use "remainder" after this line!
} else it
}
gracias, con el ejemplo, tiene mucho sentido. –
Odersky y Spoon escribieron una buena introducción a las clases de la colección Scala: ver http://www.scala-lang.org/docu/files/collections-api/collections.html –
He probado esto en Scala 2.11.7, iterator se comporta de manera similar a iterable, es decir, cuando invocas 'take (2)' por segunda vez, todavía obtienes 'List (1, 2)'. – qed