0Pricing
Kotlin Academy · Урок

Цепочки конвейеров и отказ от промежуточных списков с Sequence

Создавайте многоэтапные конвейеры и используйте Sequence для ленивого вычисления.

«Цепочки конвейеров и отказ от промежуточных списков с Sequence» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Проблема: промежуточные списки

Каждая операция над коллекцией (фильтрация, преобразование и т. д.) создаёт новый список. Для больших коллекций или длинных цепочек это приводит к лишним затратам памяти и времени.

Жадное и ленивое вычисление

Операции над коллекциями выполняются жадно: каждый шаг полностью обрабатывает список до перехода к следующему. Операции над последовательностями выполняются лениво: один элемент проходит через все шаги обработки, прежде чем начинается обработка следующего.

Преобразование в последовательность

Вызовите asSequence(), чтобы переключиться с жадной обработки (списка) на ленивую обработку (последовательности).
val result = (1..1_000_000)
    .asSequence()
    .filter { it % 2 == 0 }
    .map { it * it }
    .take(5)
    .toList()
println(result)  // [4, 16, 36, 64, 100]

Последовательность ленива: работа начинается только на конечной операции

Вычисления не выполняются, пока Вы не вызовете конечный оператор (toList, first, sum и т. д.).
val seq = generateSequence(1) { it + 1 }  // infinite!
    .filter { it % 3 == 0 }
    .map { it * it }
val first5 = seq.take(5).toList()
println(first5)  // [9, 36, 81, 144, 225]

generateSequence: бесконечные последовательности

generateSequence создаёт ленивые бесконечные последовательности.
val fibonacci = generateSequence(Pair(0, 1)) { (a, b) -> Pair(b, a + b) }
    .map { it.first }
val first10 = fibonacci.take(10).toList()
println(first10)  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Конструктор последовательности

Конструктор sequence { } с yield создаёт пользовательские ленивые последовательности.
val evens = sequence {
    var n = 0
    while (true) {
        yield(n)
        n += 2
    }
}
println(evens.take(5).toList())  // [0, 2, 4, 6, 8]

Когда использовать последовательность

Используйте Sequence, если коллекция большая (более 1000 элементов), Вы применяете несколько операций в цепочке и/или Вам нужен только небольшой набор результатов.

Когда НЕ следует использовать последовательность

Для небольших коллекций (менее 100 элементов) последовательности создают дополнительные затраты. Механизм на основе итератора работает медленнее в коротких цепочках.
// Overkill for small list:
listOf(1, 2, 3).asSequence().map { it * 2 }.toList()
// Just use:
listOf(1, 2, 3).map { it * 2 }

Конечные операции последовательности

Конечные операции запускают обработку. Распространённые варианты: toList(), first(), last(), count(), sum(), any(), all(), none().
val s = (1..100).asSequence().filter { it % 7 == 0 }
println(s.first())          // 7
println(s.count())          // 14
println(s.sum())            // 728

Состояниезависимые и независимые операции

Некоторые операции над последовательностями зависят от состояния (сортировка, удаление дубликатов): им нужно увидеть все элементы до формирования результата. Они нарушают ленивое вычисление.
val s = (1..10).asSequence()
    .filter { it > 3 }   // stateless: lazy
    .sorted()            // stateful: must see all elements
    .take(3).toList()
println(s)  // [4, 5, 6]

constrainOnce: безопасность однократной итерации

Используйте constrainOnce(), чтобы при повторной итерации последовательности возникало исключение — это полезно для потоков данных.
val seq = generateSequence(1) { if (it < 5) it + 1 else null }
    .constrainOnce()
val first = seq.toList()   // OK
// val second = seq.toList()  // IllegalStateException!

Быстрая проверка

Когда Sequence начинает обрабатывать элементы?

Повторение

Последовательности ленивы: работа не выполняется до конечного оператора. Используйте asSequence() для больших коллекций с несколькими операциями в цепочке. generateSequence и sequence { } создают бесконечные ленивые потоки. Конечные операторы запускают обработку.

Часто задаваемые вопросы

Урок «Цепочки конвейеров и отказ от промежуточных списков с Sequence» бесплатный?

Да — полный текст урока «Цепочки конвейеров и отказ от промежуточных списков с Sequence» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Цепочки конвейеров и отказ от промежуточных списков с Sequence»?

Создавайте многоэтапные конвейеры и используйте Sequence для ленивого вычисления. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Цепочки конвейеров и отказ от промежуточных списков с Sequence»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. map и flatMap: преобразование каждого элемента
  2. filter, filterNot и partition
  3. fold, reduce и runningFold
  4. Цепочки конвейеров и отказ от промежуточных списков с Sequence
← Назад к Kotlin Academy