54

IteratorIterablescalaの違いは何ですか?

Iterableこれは、反復できるセットを表しておりIterator、反復可能なセットのアイテムの1つへの「ポインター」であると思いました。

ただし、、、などのIterator関数があります。経由で変換できます。そして、たとえば、ではなく、を返します。forEachmapfoldLeftIterabletoIterablescala.io.Source.getLinesIteratorIterable

しかし、私はそれを行うことはできませんgroupByIterator、私はそれを行うことができますIterable

Iteratorでは、これら2つの関係はどうなっているのIterableでしょうか。

4

2 に答える 2

69

つまり、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。これは、使用するのが難しいためです。hasNextnext期待どおりに機能することが保証されているのは、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
}
于 2012-07-02T23:12:10.567 に答える
6

マーティンオーダスキーとレックススプーンからの別の説明:

イテレータのforeachメソッドと、トラバース可能なコレクションの同じメソッドには重要な違いがあります。イテレータに呼び出されると、foreachは、実行が完了するとイテレータを最後に残します。したがって、同じイテレータでnextを再度呼び出すと、NoSuchElementExceptionで失敗します。対照的に、コレクションで呼び出された場合、foreachはコレクション内の要素の数を変更せずに残します(渡された関数が要素を削除するために追加されない限り、これはお勧めできません。驚くべき結果につながる可能性があるためです)。

ソース:http ://www.scala-lang.org/docu/files/collections-api/collections_43.html

また、(このヒントを提供してくれたWei-Ching Linに感謝します)特性をIterator拡張しますが、拡張しません。TraversableOnceIterable

于 2015-02-06T19:54:16.487 に答える