Оператор zip позволяет объединить два потока данных:
fun <T1, T2, R> Flow<T1>.zip( other: Flow<T2>, transform: suspend (T1, T2) -> R ): Flow<R> (source)
Оператор zip
принимает два параметра. Первый параметр - поток данных, с которым надо выполнить объединение. Второй параметр - собственно функция объединения.
Она принимает соответствующие элементы обоих потоков в качестве параметров и возвращает результат их объединения.
Например, соединим два потока:
import kotlinx.coroutines.flow.* suspend fun main(){ val english = listOf("red", "yellow", "blue").asFlow() val russian = listOf("красный", "желтый", "синий").asFlow() english.zip(russian) { a, b -> "$a: $b" } .collect { word -> println(word) } }
Здесь оператор zip последовательно перебирает элементы из обоих потоков - english и russian. Элемент первого потока, на котором вызывается
оператор zip
, передается в параметр a
, а элемент второго потока - в параметр b
. Функция соединения объединяет оба элемента в одну строку.
И каждая такая строка из двух элементов передается в качестве элемента в новый создаваемый поток. Консольный вывод программы:
red: красный yellow: желтый blue: синий
Хотя в примере выше оператор zip
объединял потоки одного типа - String и возвращал поток того же типа, но в реальности объединяемые потоки
могут представлять разные данные, а возвращаемый поток - еще один тип данных:
import kotlinx.coroutines.flow.* suspend fun main(){ val names = listOf("Tom", "Bob", "Sam").asFlow() val ages = listOf(37, 41, 25).asFlow() names.zip(ages) { name, age -> Person(name, age) } .collect { person -> println("Name: ${person.name} Age: ${person.age}") } } data class Person(val name: String, val age: Int)
В данном случае функция zip
, которая вызывается на потоке типа String, объединяет его элементы с элементами потока типа Int. Причем результатом
такого объединения становится поток объектов типа Person. Результат работы программы:
Name: Tom Age: 37 Name: Bob Age: 41 Name: Sam Age: 25