Функция высшего порядка map
позволяет применить заданную функцию к каждому элементу коллекции и вернуть новую коллекцию, содержащую результаты применения этой функции.
fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
где
T
— тип элементов исходной коллекции.R
— тип элементов результирующей коллекции.transform
— функция, которая принимает элемент типаT
и возвращает элемент типаR
.
Примеры использования:
Преобразование списка целых чисел в список строк
val numbers = listOf(1, 2, 3, 4, 5)
val strings = numbers.map { it.toString() }
println(strings) // Вывод: [1, 2, 3, 4, 5]
Удвоение каждого элемента списка
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
println(doubled) // Вывод: [2, 4, 6, 8, 10]
Функция flatten
используется для объединения вложенных коллекций (например, списков списков) в одну плоскую коллекцию. Она применяется к коллекциям, элементами которых являются другие коллекции, и возвращает один плоский список, содержащий все элементы из вложенных коллекций.
fun <T> Iterable<Iterable<T>>.flatten(): List<T>
Примеры использования
Объединение списка списков в плоский список
val listOfLists = listOf(
listOf(1, 2, 3),
listOf(4, 5),
listOf(6, 7, 8)
)
val flatList = listOfLists.flatten()
println(flatList) // Вывод: [1, 2, 3, 4, 5, 6, 7, 8]
Функция высшего порядка flatMap
объединяет в себе возможности map
и flatten
. Она применяется к коллекциям (спискам, множествам, массивам и т.д.) и позволяет преобразовать каждый элемент коллекции в другую коллекцию, а затем объединить все полученные коллекции в одну плоскую коллекцию.
fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
где
T
— тип элементов исходной коллекции.R
— тип элементов результирующей коллекции.transform
— функция, которая преобразует каждый элемент типаT
в коллекцию типаIterable<R>
.
Примеры использования
Преобразование списка списков в плоский список.
val listOfLists = listOf(
listOf(1, 2, 3),
listOf(4, 5),
listOf(6, 7, 8)
)
val flatList = listOfLists.flatMap { it }
println(flatList) // Вывод: [1, 2, 3, 4, 5, 6, 7, 8]
Преобразование списка строк в список символов
val strings = listOf("apple", "banana", "cherry")
val chars = strings.flatMap { it.toList() }
println(chars) // Вывод: [a, p, p, l, e, b, a, n, a, n, a, c, h, e, r, r, y]
Функция высшего порядка associate
используется для преобразования коллекции в ассоциативный массив Map
, где каждый элемент коллекции преобразуется в пару ключ-значение.
fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>
где
T
— тип элементов исходной коллекции.K
— тип ключей в результирующемMap
.V
— тип значений в результирующемMap
.transform
— функция, которая принимает элемент типаT
и возвращает паруPair<K, V>
.
Примеры использования:
Преобразования множества целых чисел в Map
с квадратами чисел в качестве значений
val numbers = setOf(1, 2, 3, 4, 5)
val numberToSquareMap = numbers.associate { it to it * it }
println(numberToSquareMap) // Вывод: {1=1, 2=4, 3=9, 4=16, 5=25}
Функция groupBy
используется для группировки элементов коллекции по заданному ключу. Результатом является Map
, где ключом является значение, возвращаемое функцией-селектором, а значением — список элементов, которые соответствуют этому ключу. Эта функция особенно полезна, когда необходимо сгруппировать элементы по определенному признаку.
fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>
где
T
— тип элементов исходной коллекции.K
— тип ключей в результирующемMap
.keySelector
— функция, которая принимает элемент исходной коллекции и возвращает ключ типаK
. Эта функция определяет, по какому признаку будут группироваться элементы.
Примеры использования
Группировка строк по первой букве
val strings = listOf("Afghanistan", "Albania", "Algeria", "Bahamas", "Bahrain")
val groupedByFirstLetter = strings.groupBy { it.first() }
println(groupedByFirstLetter)
// Вывод: {A=[Afghanistan, Albania, Algeria], B=[Bahamas, Bahrain]}
Функция высшего порядка filter
позволяет отфильтровать элементы коллекции на основе заданного условия и вернуть новую коллекцию, содержащую только те элементы, которые удовлетворяют этому условию.
fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
где,
T
— тип элементов исходной коллекции.predicate
— функция, которая принимает элемент исходной коллекции и возвращаетBoolean
, определяя должен ли он быть включен в результирующую коллекцию.
Примеры использования
Фильтрация четных чисел
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // Вывод: [2, 4, 6, 8, 10]
Фильтрация строк по длине
val strings = listOf("apple", "banana", "cherry", "date", "elderberry")
val longStrings = strings.filter { it.length > 5 }
println(longStrings) // Вывод: ["banana", "cherry", "elderberry"]
Функция zip
используется для объединения двух коллекций в одну, создавая пары элементов из каждой коллекции. Результатом является новая коллекция, содержащая пары элементов, где каждая пара состоит из элемента из первой коллекции и соответствующего элемента из второй коллекции. Если коллекции имеют разную длину, результат будет содержать только пары, созданные до достижения конца более короткой коллекции.
fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>>
где
T
— тип элементов первой коллекции.R
— тип элементов второй коллекции.
Примеры использования
Объединение двух списков
val list1 = listOf(1, 2, 3)
val list2 = listOf("a", "b", "c")
val zippedList = list1.zip(list2)
println(zippedList) // Вывод: [(1, "a"), (2, "b"), (3, "c")]
Объединение списков разной длины
val list1 = listOf(1, 2, 3, 4)
val list2 = listOf("a", "b")
val zippedList = list1.zip(list2)
println(zippedList) // Вывод: [(1, "a"), (2, "b")]
Функция reduce
используется для агрегирования элементов коллекции в одно значение, применяя заданную операцию к каждому элементу последовательно. Она начинает с первых двух элементов, применяет к ним операцию, затем применяет операцию к результату и следующему элементу, и так далее, пока не будут обработаны все элементы коллекции.
fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S
где
T
— тип элементов исходной коллекции.S
— тип результирующего значения.operation
— функция, которая принимает два аргумента: аккумулятор (acc
) и текущий элемент коллекции, и возвращает новое значение аккумулятора.
Примеры использования
Сумма элементов списка
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.reduce { acc, number -> acc + number }
println(sum) // Вывод: 15
Объединение строк
val strings = listOf("a", "b", "c", "d")
val concatenated = strings.reduce { acc, string -> acc + string }
println(concatenated) // Вывод: "abcd"
Функция fold
используется для агрегирования элементов коллекции в одно значение, начиная с начального значения (аккумулятора) и применяя заданную операцию к каждому элементу последовательно. В отличие от reduce
, fold
позволяет задать начальное значение аккумулятора.
fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R
где
T
— тип элементов исходной коллекции.R
— тип результирующего значения.operation
— функция, которая принимает два аргумента: аккумулятор (acc
) и текущий элемент коллекции, и возвращает новое значение аккумулятора.
Примеры использования
Сумма элементов списка с начальным значением
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.fold(1000) { acc, number -> acc + number }
println(sum) // Вывод: 1015
Функция sumBy
используется для вычисления суммы элементов коллекции, применяя заданную функцию преобразования к каждому элементу перед суммированием. Результатом является сумма всех преобразованных значений. Эта функция особенно полезна, когда вам нужно суммировать не сами элементы, а результаты их преобразования.
fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int
где
T
— тип элементов исходной коллекции.Int
— тип результирующего значения.selector
— функция, которая принимает элемент типа исходной коллекции и возвращает целое число. Эта функция определяет, как преобразовать каждый элемент перед суммированием.
Примеры использования
Сумма длин строк
val strings = listOf("apple", "banana", "cherry")
val totalLength = strings.sumBy { it.length }
println(totalLength) // Вывод: 17
Последовательности (Sequences) — это наборы данных, которые позволяют выполнять операции над своими элементами "отложенным" образом (lazy), т. е. по одному элементу за раз, только когда это необходимо. В отличие от обычных коллекций (списков, множеств и т.д.), которые выполняют все операции сразу, последовательности выполняют операции по мере их потребности, что может значительно повысить производительность, особенно при работе с большими наборами данных.
Основные характеристики последовательностей:
- Отложенность: Операции над последовательностями выполняются только тогда, когда это необходимо. Например, если вы выполняете фильтрацию и преобразование последовательности, эти операции будут выполняться по одному элементу за раз, а не для всей коллекции сразу.
- Однопроходность: Последовательности могут быть пройдены только один раз. После того как последовательность была полностью пройдена, она считается исчерпанной и не может быть использована снова.
- Отложенное выполнение: Результаты операций над последовательностями не вычисляются до тех пор, пока не будет вызвана функция, которая требует их (
toList()
,first()
,forEach()
и др.).
Последовательности можно создавать несколькими способами:
- Из коллекции, используя метод
asSequence()
. - Из диапазона, используя функцию
sequenceOf()
. - Из генератора, используя функцию
generateSequence()
.
// Создание последовательности из списка
val list = listOf(1, 2, 3, 4, 5)
val sequenceFromList = list.asSequence()
// Создание последовательности из диапазона
val sequenceFromRange = sequenceOf(1, 2, 3, 4, 5)
// Создание последовательности с использованием генератора
val sequenceFromGenerator = generateSequence(1) { it + 1 }
Последовательности поддерживают множество операций, аналогичных операциям над обычными коллекциями, таких как map
, filter
, flatMap
, и др. Однако, в отличие от коллекций, эти операции выполняются "отложенным" образом.
Примеры операций над последовательностями
val numbers = sequenceOf(1, 2, 3, 4, 5)
// Фильтрация и преобразование
val evenSquares = numbers
.filter { it % 2 == 0 }
.map { it * it }
println(evenSquares.toList()) // Вывод: [4, 16]
// Взятие первых 3 элементов
val firstThree = numbers.take(3)
println(firstThree.toList()) // Вывод: [1, 2, 3]
// Пропуск первых 2 элементов
val skipTwo = numbers.drop(2)
println(skipTwo.toList()) // Вывод: [3, 4, 5]
Функция measureNanoTime
используется для измерения времени выполнения блока кода в наносекундах. Это особенно полезно при профилировании и оптимизации производительности кода, так как позволяет точно определить, сколько времени занимает выполнение конкретного участка кода.
inline fun measureNanoTime(block: () -> Unit): Long
где
block
— функция, представляющая блок кода, время выполнения которого нужно измерить.
Примеры использования
Измерение времени выполнения функции суммирования
fun main() {
fun sum() {
var sum = 0
for (i in 1..1000000) {
sum += i
}
}
val time = measureNanoTime { sum() }
println("Время выполнения функции sum: $time наносекунд")
}
Измерение времени выполнения сортировки списка
fun main() {
val list = (1..1000000).shuffled()
val time = measureNanoTime {
list.sorted()
}
println("Время выполнения сортировки: $time наносекунд")
}
Функция measureTimeMillis
используется для измерения времени выполнения блока кода в миллисекундах. Это полезно при профилировании и оптимизации производительности кода, так как позволяет определить, сколько времени занимает выполнение конкретного участка кода.
inline fun measureTimeMillis(block: () -> Unit): Long
где
block
— функция, представляющая блок кода, время выполнения которого нужно измерить.
Примеры использования
Измерение времени выполнения простого цикла
fun main() {
val time = measureTimeMillis {
var sum = 0
for (i in 1..1000000) {
sum += i
}
}
println("Время выполнения: $time миллисекунд")
}
Измерение времени выполнения рекурсивной функции
fun factorial(n: Int): Int {
return if (n == 1) 1 else n * factorial(n - 1)
}
fun main() {
val time = measureTimeMillis {
factorial(10)
}
println("Время выполнения факториала: $time миллисекунд")
}
Часть I
- Возведение в степень элементов списка. Напишите программу, которая принимает список целых чисел и целое число
n
(степень), и возвращает новый список, в котором каждый элемент является результатом возведения соответствующего элемента исходного списка в степеньn
. - Преобразование списка строк в список их длин. Напишите программу, которая принимает список строк и возвращает список, содержащий длины этих строк.
- Преобразование списка чисел в список их двоичных представлений. Напишите программу, которая принимает список целых чисел и возвращает новый список, в котором каждый элемент является двоичным представлением соответствующего элемента исходного списка.
- Преобразование списка строк в список их уникальных символов. Напишите программу, которая принимает список строк и возвращает список, содержащий уникальные символы каждой строки.
- Преобразование списка пар в список строк. Напишите программу, которая принимает список пар (Pair) строк и целых чисел и возвращает список строк вида "Строка: Число".
- Преобразование списка троек в список произведений. Напишите программу, которая принимает список троек (Triple) целых чисел и возвращает список, содержащий произведения элементов каждой тройки.
- Создание ассоциативного массива из списка пар. Напишите программу, которая преобразует список пар (Pair) вида (строка, целое число) в ассоциативный массив (Map), где ключом является строка, а значением — целое число.
- Преобразование списка списков в список четных чисел. Напишите программу, которая преобразует этот список списков целых чисел в список четных чисел, содержащий все четные числа из всех списков.
- Преобразование списка пар в список значений. Имеется список пар (Pair) вида (строка, список целых чисел). Напишите программу, которая преобразует этот список в список целых чисел, содержащий все элементы из всех списков.
Часть II
- Фильтрация простых чисел. Напишите программу, которая принимает список целых чисел и возвращает новый список, содержащий только простые числа.
- Фильтрация списка чисел на числа, делящиеся на 3 и 5. Напишите программу, которая принимает список целых чисел и возвращает новый список, содержащий только числа, которые делятся на 3 и на 5 одновременно.
- Фильтрация строк, содержащих определенную подстроку. Напишите программу, которая принимает список строк и возвращает новый список, содержащий только строки, которые содержат заданную подстроку.
- Фильтрация списка строк по регулярному выражению. Напишите программу, которая принимает список строк и возвращает новый список, содержащий только строки, которые являются адресами электронной почты.
- Генерация последовательности Фибоначчи. Напишите программу, которая генерирует бесконечную последовательность чисел Фибоначчи и выводит первые 10 элементов.
- Фильтрация и преобразование бесконечной последовательности. Напишите программу, которая генерирует бесконечную последовательность целых чисел, начиная с 1, фильтрует ее, оставляя только четные числа, удваивает каждый элемент и выводит первые 5 элементов результата.
- Фильтрация и преобразование последовательности строк. Напишите программу, которая создает последовательность из списка строк, фильтрует ее, оставляя только строки, длина которых больше 5 символов, преобразует каждую строку в верхний регистр и выводит результат.
- Комбинирование (объединение) списка строк и списка чисел. Напишите программу, которая принимает список строк и список целых чисел и возвращает новый список пар, где каждая пара состоит из строки и числа с одинаковыми индексами.
- Комбинирование (объединение) списка дат и списка событий с преобразованием. Напишите программу, которая принимает список дат (объектов класса
LocalDate
) и список событий (строк) и возвращает новый список строк вида "Дата: Событие", где каждая строка состоит из даты и события с одинаковыми индексами. - Сумма элементов списка с использованием. Напишите программу, которая принимает список целых чисел и возвращает сумму всех элементов с использованием функции
reduce
. - Сумма цен товаров с использованием. Напишите программу, которая принимает список пар вида (наименование товара, цена) и возвращает сумму цен всех товаров с использованием функции
sumBy
.
Часть III
Профилирование алгоритмов сортировки. Проведите профилирование нескольких алгоритмов сортировки с использованием функций measureNanoTime
и measureTimeMillis
из стандартной библиотеки Kotlin. Необходимо сравнить производительность различных алгоритмов сортировки и выявить наиболее эффективные решения.
- Реализуйте три различных алгоритма сортировки:
- Пузырьковая сортировка (Bubble Sort)
- Сортировка слиянием (Merge Sort)
- Быстрая сортировка (Quick Sort)
- Создайте функцию для генерации списка случайных чисел:
- Функция должна принимать два параметра: размер списка и диапазон значений.
- Проведите профилирование каждого алгоритма сортировки:
- Используйте функцию
measureNanoTime
для измерения времени выполнения в наносекундах. - Используйте функцию
measureTimeMillis
для измерения времени выполнения в миллисекундах. - Проведите профилирование для списков различных размеров (1000, 10000, 100000 элементов).
- Используйте функцию
- Сравните результаты профилирования:
- Выведите результаты в виде таблицы.
- Проанализируйте, какой алгоритм является наиболее эффективным для каждого размера списка.
- Оптимизируйте один из алгоритмов сортировки:
- Выберите один из алгоритмов и попытайтесь оптимизировать его.
- Проведите повторное профилирование и сравните результаты с исходным алгоритмом.
- Преобразование данных
- Фильтрация данных
- Комбинирование данных
- Агрегирование данных
- Последовательности
- Профилирование