W skrócie: Iterator
ma stan, natomiast Iterable
nie.
Zobacz dokumentację interfejsu API dla obu.
Iterable:
Cechą bazą dla kolekcji iterable.
Jest to podstawowa cecha dla wszystkich kolekcji Scala, które definiują metodę iteratora , aby krok po kroku przenosić elementy kolekcji. [...] Ta cecha implementuje metodę foreach Iterable, wprowadzając przez wszystkie elementy za pomocą iteratora.
Iterator:
Iterators są struktury danych, które pozwalają na iteracyjnego sekwencję elementów. Mają metodę hasNext do sprawdzenia, czy dostępny jest następny element , i następną metodę, która zwraca następny element i odrzuca go z iteratora.
Iterator jest zmienny: większość operacji na nim zmienia swój stan. Podczas gdy jest często wykorzystywany do iteracji elementów kolekcji, można go również używać bez konieczności tworzenia kopii zapasowej przez dowolny zbiór (patrz konstruktory w obiekcie towarzyszącym).
Dzięki Iterator
możesz zatrzymać iterację i kontynuować ją później, jeśli chcesz. Jeśli spróbujesz zrobić to z Iterable
rozpocznie się od głowy znowu:
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 =()
uwaga, że nie używałem take
na Iterator
. Powodem tego jest to, że jest trudny w użyciu. hasNext
i next
to jedyne dwie metody, które działają zgodnie z oczekiwaniami na Iterator
.Zobacz kolejny Scaladoc:
Jest to szczególnie ważne, aby pamiętać, że o ile nie zaznaczono inaczej, nigdy nie należy używać iterator po wywołaniu metody na nim. Dwa najważniejsze wyjątki to również jedyne abstrakcyjne metody: next i hasNext.
Obie te metody można wywoływać dowolną liczbę razy bez konieczności odrzucania iteratora przez . Zauważ, że nawet hasNext może powodować mutację - , na przykład podczas iteracji ze strumienia wejściowego, gdzie będzie blokować do momentu zamknięcia strumienia lub udostępnienia niektórych danych wejściowych.
Rozważmy następujący przykład dla bezpiecznego i niebezpiecznego użycia:
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
}
dzięki, na przykład, ma to sens. –
Odersky i Spoon napisali dobry primer na temat klas kolekcji Scala: zobacz http://www.scala-lang.org/docu/files/collections-api/collections.html –
Przetestowałem to w Scali 2.11.7, iterator zachowuje się podobnie do iteracji, a mianowicie, gdy po raz drugi wywołujesz 'take (2)', nadal otrzymujesz 'List (1, 2)'. – qed