つまり、AnIterator
には状態がありますが、anにIterable
はありません。
両方のAPIドキュメントを参照してください。
反復可能:
反復可能なコレクションの基本特性。
これは、コレクションの要素を1つずつステップスルーするイテレーターメソッドを定義するすべてのScalaコレクションの基本特性です。[...]このトレイトは、イテレータを使用してすべての要素をステップスルーすることにより、Iterableのforeachメソッドを実装します。
イテレータ:
イテレータは、要素のシーケンスを反復処理できるデータ構造です。使用可能な次の要素があるかどうかを確認するためのhasNextメソッドと、次の要素を返し、イテレーターから破棄するnextメソッドがあります。
イテレータは変更可能です。イテレータに対するほとんどの操作は、その状態を変更します。コレクションの要素を反復処理するためによく使用されますが、コレクションに支えられずに使用することもできます(コンパニオンオブジェクトのコンストラクターを参照)。
を使用するIterator
と、反復を停止して、必要に応じて後で続行できます。あなたがこれを使ってこれを行おうとすると、Iterable
それは再び頭から始まります:
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 = ()
take
で使用しなかったことに注意してくださいIterator
。これは、使用するのが難しいためです。hasNext
でnext
期待どおりに機能することが保証されているのは、2つの方法だけIterator
です。Scaladocをもう一度参照してください。
特に明記されていない限り、メソッドを呼び出した後はイテレータを使用しないでください。最も重要な2つの例外は、nextとhasNextの唯一の抽象メソッドでもあります。
これらのメソッドは両方とも、イテレータを破棄せずに何度でも呼び出すことができます。hasNextでさえ、ミューテーションを引き起こす可能性があることに注意してください。たとえば、入力ストリームから反復する場合、ストリームが閉じられるか、一部の入力が使用可能になるまでブロックされます。
安全な使用と安全でない使用のために、この例を検討してください。
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
}