Вкратце: у Iterator
есть состояние, а Iterable
- нет.
См. Документы API для обоих.
Iterable:
Базовая черта для Iterable коллекций.
Это базовая черта для всех коллекций Scala, которые определяют метод итератора для того, чтобы каждый элемент пошагового элемента. [...] Эта черта реализует метод foreach Iterable, шаг за шагом через все элементы, использующие итератор.
Iterator:
итераторы представляют собой структуры данных, которые позволяют перебирать последовательность элементов. У них есть метод hasNext для проверки наличия следующего элемента и следующего метода, который возвращает следующий элемент и удаляет его из итератора.
Итератор изменчив: большинство операций на нем меняет свое состояние. В то время как он часто используется для итерации элементов коллекции, он может быть использован без поддержки какой-либо коллекции (см. конструкторы на сопутствующем объекте).
С помощью 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
- это только два метода, которые гарантированно работают как ожидается на 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
}
спасибо, с примером, это имеет смысл. –
Odersky and Spoon написал хороший пример для классов коллекции Scala: см. http://www.scala-lang.org/docu/files/collections-api/collections.html –
Я тестировал это в Scala 2.11.7, Итератор ведет себя аналогично итерабельному, а именно, когда вы вызываете 'take (2)' во второй раз, вы все равно получаете 'List (1, 2)'. – qed