scala Iterable 和 Iterator 之间是什么关系?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11302270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:18:29  来源:igfitidea点击:

What is the relation between Iterable and Iterator?

scalaiterator

提问by Karel Bílek

What is the difference between Iteratorand Iterablein scala?

IteratorIterable在 Scala 中有什么区别?

I thought that Iterablerepresents a set that I can iterate through, and Iteratoris a "pointer" to one of the items in the iterable set.

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

However, Iteratorhas functions like forEach, map, foldLeft. It can be converted to Iterablevia toIterable. And, for example, scala.io.Source.getLinesreturns Iterator, not Iterable.

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

But I cannot do groupByon Iteratorand I can do it on Iterable.

但我不能做groupByIterator,我能做到这一点的Iterable

So, what's the relation between those two, Iteratorand Iterable?

那么,这两者之间有什么关系,Iterator以及Iterable

回答by kiritsuku

In short: An Iteratordoes have state, whereas an Iterabledoes not.

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

See the API docs for both.

请参阅两者的 API 文档。

Iterable:

可迭代的

A base trait for iterable collections.

This is a base trait for all Scala collections that define an iterator method to step through one-by-one the collection's elements. [...] This trait implements Iterable's foreach method by stepping through all elements using iterator.

可迭代集合的基本特征。

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

Iterator:

迭代器

Iterators are data structures that allow to iterate over a sequence of elements. They have a hasNext method for checking if there is a next element available, and a next method which returns the next element and discards it from the iterator.

An iterator is mutable: most operations on it change its state. While it is often used to iterate through the elements of a collection, it can also be used without being backed by any collection (see constructors on the companion object).

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

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

With an Iteratoryou can stop an iteration and continue it later if you want. If you try to do this with an Iterableit will begin from the head again:

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

Note, that I didn't use takeon Iterator. The reason for this is that it is tricky to use. hasNextand nextare the only two methods that are guaranteed to work as expected on Iterator. See the Scaladocagain:

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

It is of particular importance to note that, unless stated otherwise, one should never use an iterator after calling a method on it. The two most important exceptions are also the sole abstract methods: next and hasNext.

Both these methods can be called any number of times without having to discard the iterator. Note that even hasNext may cause mutation -- such as when iterating from an input stream, where it will block until the stream is closed or some input becomes available.

Consider this example for safe and unsafe use:

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
}

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

回答by bjfletcher

Another explanation from Martin Odersky and Lex Spoon:

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

There's an important difference between the foreach method on iterators and the same method on traversable collections: When called to an iterator, foreach will leave the iterator at its end when it is done. So calling next again on the same iterator will fail with a NoSuchElementException. By contrast, when called on on a collection, foreach leaves the number of elements in the collection unchanged (unless the passed function adds to removes elements, but this is discouraged, because it may lead to surprising results).

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

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

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

Note also (thanks to Wei-Ching Lin for this tip) Iteratorextends the TraversableOncetrait while Iterabledoesn't.

还要注意(感谢 Wei-Ching Lin 的提示)Iterator扩展了TraversableOncetrait 而Iterable没有扩展。