Операторы Flow: map, filter, transform и take
Применяйте промежуточные операторы для преобразования и ограничения выдачи Flow.
«Операторы Flow: map, filter, transform и take» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Что такое поток
Flow — это холодный асинхронный поток. Промежуточные операторы, такие как map, filter и transform, выполняются лениво — только при сборе потока.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbers(): Flow<Int> = flow {
repeat(5) { emit(it + 1) }
}
fun main() = runBlocking {
numbers().collect { println(it) }
}Оператор преобразования
map преобразует каждое выданное значение. Это преобразование один к одному, применяемое лениво.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..5).asFlow()
.map { it * it }
.collect { println(it) } // 1 4 9 16 25
}Оператор фильтрации
filter пропускает только элементы, соответствующие условию, отбрасывая остальные.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..10).asFlow()
.filter { it % 2 == 0 }
.collect { println(it) } // 2 4 6 8 10
}Оператор трансформации
transform — самый универсальный оператор: для каждого входного элемента можно выдать ноль, одно или несколько значений.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..3).asFlow()
.transform { n ->
emit("Item $n")
emit("Done $n")
}
.collect { println(it) }
}Оператор ограничения количества
take(n) получает только первые n элементов, а затем отменяет исходный поток.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
repeat(100) { emit(it) }
}.take(3)
.collect { println(it) } // 0 1 2
}Отбор и пропуск по условию
takeWhile получает элементы, пока условие истинно, а dropWhile пропускает элементы, пока условие не станет ложным.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..10).asFlow()
.takeWhile { it < 5 }
.collect { println(it) } // 1 2 3 4
(1..10).asFlow()
.dropWhile { it < 5 }
.collect { println(it) } // 5 6 7 8 9 10
}Объединение операторов в цепочку
Операторы можно компоновать: каждый оператор возвращает новый Flow, что позволяет создавать декларативные конвейеры.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..20).asFlow()
.filter { it % 3 == 0 }
.map { it * 2 }
.take(4)
.collect { println(it) } // 6 12 18 24
}Преобразование с отбрасыванием нулевых значений
mapNotNull за один шаг преобразует значения и отбрасывает результаты null — это эквивалентно конструкции map + filter { it != null }.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf("1", "two", "3", "four", "5")
.mapNotNull { it.toIntOrNull() }
.collect { println(it) } // 1 3 5
}Последовательное объединение потоков
flatMapConcat преобразует каждый элемент в поток и последовательно объединяет результаты.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..3).asFlow()
.flatMapConcat { n -> flowOf("$n-a", "$n-b") }
.collect { println(it) }
}Побочные эффекты для каждого элемента
onEach выполняет побочное действие для каждого элемента, не изменяя поток, — это удобно для ведения журнала или аналитики в конвейере.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..5).asFlow()
.onEach { println("Processing: $it") }
.filter { it % 2 == 0 }
.collect { println("Collected: $it") }
}Поток является холодным
Каждый вызов collect запускает поток заново. Ни один элемент не выдаётся и не преобразуется, пока терминальный оператор не инициирует сбор.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow = (1..3).asFlow().map { println("map $it"); it * 2 }
println("Before collect")
flow.collect { println("got $it") }
println("Second collect:")
flow.collect { println("got $it") } // runs again
}Быстрая проверка
Какой оператор выдаёт ноль, одно или несколько значений для каждого элемента исходного потока?
Итоги
Преобразование выполняется один к одному; фильтрация отбрасывает элементы; трансформация выдаёт любое количество значений; ограничение ограничивает их число. Объединяйте операторы в декларативную цепочку — поток является холодным и выполняется только при сборе.
Часто задаваемые вопросы
Урок «Операторы Flow: map, filter, transform и take» бесплатный?
Да — полный текст урока «Операторы Flow: map, filter, transform и take» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Операторы Flow: map, filter, transform и take»?
Применяйте промежуточные операторы для преобразования и ограничения выдачи Flow. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Операторы Flow: map, filter, transform и take»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Операторы Flow: map, filter, transform и take
- catch и onCompletion: обработка ошибок в Flow
- combine и zip: объединение нескольких Flow
- flowOn и buffer: контекст и противодавление