54

scalaIterator和in有什么区别?Iterable

我认为这Iterable代表了一个我可以迭代的集合,并且Iterator是指向可迭代集合中的一个项目的“指针”。

但是,Iterator具有forEach, map,等功能foldLeft。它可以转换为Iterablevia toIterable。并且,例如,scala.io.Source.getLines返回Iterator,而不是Iterable

但我不能做groupByIterator我可以做Iterable

那么,这两者之间是什么关系,IteratorIterable

4

2 回答 2

69

简而言之:AnIterator确实有状态,而 anIterable没有。

请参阅两者的 API 文档。

可迭代

可迭代集合的基本特征。

这是所有 Scala 集合的基本特征,它定义了一个迭代器方法来逐个遍历集合的元素。[...] 这个 trait 通过使用迭代器遍历所有元素来实现 Iterable 的 foreach 方法。

迭代器

迭代器是允许迭代一系列元素的数据结构。它们有一个 hasNext 方法来检查是否有下一个元素可用,还有一个 next 方法返回下一个元素并将其从迭代器中丢弃。

迭代器是可变的:对它的大多数操作都会改变它的状态。虽然它通常用于遍历集合的元素,但它也可以在没有任何集合支持的情况下使用(参见伴随对象的构造函数)。

Iterator如果需要,您可以使用 an停止迭代并在以后继续。如果您尝试使用 a 执行此操作,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 = ()

请注意,我没有使用takeon Iterator。这样做的原因是它使用起来很棘手。hasNext并且next是唯一可以保证按预期工作的两种方法Iterator。再次查看Scaladoc

特别重要的是要注意,除非另有说明,否则在调用迭代器的方法后绝不应使用迭代器。两个最重要的例外也是唯一的抽象方法: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

Martin Odersky 和 ​​Lex Spoon 的另一种解释:

迭代器上的 foreach 方法与可遍历集合上的相同方法之间有一个重要的区别:当调用迭代器时,foreach 将在迭代器完成时将迭代器留在其末尾。因此,在同一个迭代器上再次调用 next 将失败并返回 NoSuchElementException。相反,当在集合上调用时,foreach 保持集合中元素的数量不变(除非传递的函数添加到删除元素,但不鼓励这样做,因为它可能会导致令人惊讶的结果)。

来源:http ://www.scala-lang.org/docu/files/collections-api/collections_43.html

还要注意(感谢 Wei-Ching Lin 的这个提示)Iterator扩展了这个TraversableOnce特性,而Iterable没有。

于 2015-02-06T19:54:16.487 回答