Kurz gesagt: Ein Iterator
hat Zustand, während ein Iterable
nicht.
Siehe API-Dokumentation für beide.
Iterable:
Ein Grundmerkmal für iterable Sammlungen.
Dies ist eine Basiseigenschaft für alle Scala-Sammlungen, die einen Iterator definieren, mit dem die Elemente der Sammlung einzeln durchlaufen werden. [...] Diese Eigenschaft implementiert Iterable foreach Verfahren durch durch alle Elemente Schritt Iterator.
Iterator:
Iteratoren sind Datenstrukturen, die eine Folge von Elemente iterieren ermöglichen. Sie haben eine hasNext-Methode zum Überprüfen, ob ein nächstes -Element verfügbar ist, und eine nächste Methode, die das nächste Element zurückgibt und es vom Iterator verwirft.
Ein Iterator ist änderbar: Die meisten Operationen ändern seinen Zustand. Während oft verwendet wird, um durch die Elemente einer Sammlung zu iterieren, kann auch verwendet werden, ohne von einer Sammlung gesichert werden (siehe Konstruktoren auf dem Companion-Objekt).
Mit einer Iterator
können Sie eine Iteration stoppen und später fortsetzen, wenn Sie möchten. Wenn Sie versuchen, dies zu tun mit einem Iterable
wird es vom Kopf wieder beginnen:
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 =()
Beachten Sie, dass ich nicht take
auf Iterator
benutzt haben. Der Grund dafür ist, dass es schwierig zu verwenden ist. hasNext
und next
sind die einzigen zwei Methoden, die auf Iterator
wie erwartet sind garantiert zu arbeiten.die Scaladoc wieder sehen:
Es ist von besonderer Bedeutung, zu beachten, dass, wenn nicht anders angegeben, man sollte nie einen Iterator verwenden, nachdem ein Verfahren auf sie anrufen. Die beiden wichtigsten Ausnahmen sind die einzigen abstrakten Methoden: next und hasNext.
Beide Methoden können beliebig oft aufgerufen werden, ohne den Iterator verwerfen zu müssen. Beachten Sie, dass sogar hasNext eine Mutation verursachen kann - , z. B. beim Iterieren aus einem Eingabestream, wo es blockiert, bis der Stream geschlossen wird oder eine Eingabe verfügbar wird.
Betrachten Sie dieses Beispiel für den sicheren und unsicheren Gebrauch:
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
}
danke, mit dem Beispiel macht es vollkommen Sinn. –
Odersky und Spoon haben einen guten Grund auf die Scala Kollektion geschrieben: siehe http://www.scala-lang.org/docu/files/collections-api/collections.html –
Ich habe das in Scala 2.11.7 getestet, Iterator verhält sich ähnlich wie iterierbar, dh wenn Sie 'take (2)' zum zweiten Mal aufrufen, erhalten Sie immer noch 'List (1, 2)'. – qed