Итератор

Итератор

Для перебора элементов коллекции в стандартная библиотека Kotlin поддерживает общеиспользуемый механизм итераторов – объектов, которые предоставляют последовательный доступ (один за другим) к элементам без раскрытия основной структуры коллекции.

Доступ к итераторам можно получить в объектах, которые являются потомками интерфейса Iterable<T>, вызвав функцию iterator(). Итератор поначалу ссылается на первый элемент коллекции и вызвав функцию next() мы получаем текущий элемент и итератор, если существует следующий элемент, перемещается к нему. Когда итератор проходит через последний элемент, он больше не может быть использован для получения элементов и не может переместиться на предыдущие позиции. Для повторной итерации необходимо создать новый объект итератора вызвав функцию iterator():

val items = mutableListOf(1, 2, 3)
val iterator = items.iterator()
// hasNext() возвращает true если не достигнут последний элемент
while(iterator.hasNext())
{
    println(iterator.next())
}

В циклах for итератор передаётся неявно. Пример ниже является альтернативной версией предыдущего примера:

for(item in items)
{
    println(item)
}

В коллекциях есть функция forEach(), которая служит для перебора элементов коллекции аналогично предыдущим примерам. Код функции forEach() коллекции можно написать как лямбда, поэтому там переменная it неявно указывает на текущий элемент коллекции:

items.forEach(
    {
        println(it)
    }
)

ListIterator

ListIterator – специальная версия итератора, которая поддерживает итерацию в обе стороны: вперед и назад, что означает этот итератор при достижении последнего элемента можно продолжать использовать. Существование предыдущего элемента проверяется посредством функции hasPrevious(), получение доступа к текущему элементу и перемещение итератора на позиции назад осуществляется вызовом функции previous():

val items = mutableListOf(1, 2, 3)
val iterator = items.listIterator()
// Итерация от начала до конца
while(iterator.hasNext())
{
    println(iterator.next())
}
// Итерация от конца к началу
while(iterator.hasPrevious())
{
    println(iterator.previous())
}

Для итерации изменяемых коллекций доступен класс MutableIterator, который расширяет класс Iterator с возможностью удаления элементов:

val items = mutableListOf(1, 2, 3)
val iterator = items.iterator()
iterator.next() // Указать в качестве текущего первый объект
iterator.remove() // Удалить текущий (первый) объект

while(iterator.hasNext())
{
    // Вывести в консоль оставшиеся объекты
    println(iterator.next())
}
// Вывести размер объектов: было 3, после удаления первого объекта осталось 2
println("Count ${items.size}")

Через итератор можно также добавлять или  изменять элементы коллекции, для чего служат функции add и set:

val items = mutableListOf(1, 2, 3)
val iterator = items.listIterator()
// Добавить новый элемент в начало коллекции
iterator.add(0)
// Перейти к следующему объекту
iterator.next()
// Указать значение для текущего (второго) элемента коллекции
iterator.set(5)

// Перебор всех объектов коллекции
items.forEach(
    {
        // Вывести значение в консоль
        println(it)
    }
)

//Результат:
//0
//5
//2
//3