Добавить в корзинуПозвонить
Найти в Дзене

Урок 9: Списки в Kotlin, функции для работы с коллекциями | Курс обучения Kotlin с нуля

Смотреть на обучающей платформе с ИИ: https://androidsprint.ru/courses/osnovy-yazyka-kotlin-dlya-nachinayushchikh Смотреть в VK:
https://vkvideo.ru/playlist/-85562117_1/video-85562117_456239030 Смотреть на YouTube:
https://www.youtube.com/watch?v=oYA2InjQ4WQ По определению коллекции – это группы с переменным количеством элементов (или нулем элементов). Объекты внутри как правило имеют единый тип. Коллекции называются коллекциями, потому что корнем их иерархии в языке является класс Collection<T>. Позже, при изучении наследования это станет понятнее, пока не будем сильно углубляться. В этот раз подробнее остановимся на списках. Поведение напоминает работу с массивами, однако, есть существенные отличия в принципе работы. В целом хорошей практикой считается использовать списки вместо массивов везде, где это позволяет техническая реализация. Однако, с точки зрения производительности, массивы имеют над списками преимущество. Списки создаются с помощью функции listOf() из стандартной библи
Оглавление

Смотреть на обучающей платформе с ИИ: https://androidsprint.ru/courses/osnovy-yazyka-kotlin-dlya-nachinayushchikh
Смотреть в VK:
https://vkvideo.ru/playlist/-85562117_1/video-85562117_456239030
Смотреть на YouTube:
https://www.youtube.com/watch?v=oYA2InjQ4WQ

Коллекции

По определению коллекции – это группы с переменным количеством элементов (или нулем элементов). Объекты внутри как правило имеют единый тип. Коллекции называются коллекциями, потому что корнем их иерархии в языке является класс Collection<T>. Позже, при изучении наследования это станет понятнее, пока не будем сильно углубляться.

Типы коллекций

  • List (список) – упорядоченный набор элементов, к ним можно обращаться по индексам. В списке могут встречаться дубликаты.
  • Set (множество) – коллекция уникальных элементов. То есть повторяющиеся элементы исключены. Порядок элементов может быть любым.
  • Map (словарь или ассоциативным список) – определенный набор пар. Пара содержит в себе ключ и значение. Зная ключ, можно обратиться к какому-нибудь значению. Ключи строго уникальны, а значения могут иметь дубликаты.

Списки

В этот раз подробнее остановимся на списках. Поведение напоминает работу с массивами, однако, есть существенные отличия в принципе работы.

Отличия от массивов

  • Первое. Массив имеет строго фиксированный размер и не может уменьшаться или увеличиваться. Изменить размер массива можно только создав его копию с дополнительными или утраченными элементами. Списки же имеют методы add и remove для добавления/удаления элементов.
  • Второе. Массив предоставляется классом Array<T>. List<T> является интерфейсом и имеет разные реализации со своим функционалом.
  • Третье. Массивы оптимизированы для примитивов и меют отдельные типа IntArray, CharArray и т.д. Списки такой оптимизации не имеют.
  • Четвертое. Различается процесс сравнивания элементов друг с другом. В массивах сравниваются адреса ячеек в памяти, в списках же идет сравнение самого значения.

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

Создание списков в Котлин

Списки создаются с помощью функции listOf() из стандартной библиотеки Kotlin. Короткая запись создания целочисленного списка выглядит так:

-2

Если принудительно проставить тип списка, получим List. Это базовый интерфейс для всех неизменяемых списков:

-3

Его “неизменяемость” определяется тем, что нельзя просто так взять и обратиться по индексу к элементу и заменить его на другой. Как мы делали это с массивами. Также отсутствуют функции по добавлению и удалению элементов.

Изменяемые списки в Kotlin

В таких списках мы можем читать конкретное значение по индексу, а также пробегать циклом по всем значениям вместе. Но для того, чтобы создать изменяемый список, необходимо использовать функцию mutableListOf().

При данной инициализации тип переменной будет MutableList<T>. Это второй базовый интерфейс для списков, на основе которого создаются изменяемые списки. Это List с возможностью добавления или удаления элементов:

-4

Функции для работы со списками

Теперь переходим к инструментарию по работе со списками. В уроке примеры будут представлены на примере целочисленного списка. А в практике, прилагаемой к уроку, будут оформлены задачи с применением различных типов с неким прикладным контекстом.

Еще раз создадим изменяемый список с некоторым количеством чисел.

-5

Функция add()

Сначала будем добавлять значения в список с помощью функции add(). Чтобы воспользоваться ей, необходимо написать переменную со списком и вызвать для нее этот метод с помощью обращения через точку.

Метод add() может принимать два набора параметров и в зависимости от этого, будет произведены разные действия.

Первый вариант – это всего один параметр, который является новым элементом, который нужно добавить в список. Этот элемент по умолчанию добавляется в конец списка. Результат в консоли:

-6

Второй вариант – это когда метод add() принимает два параметра. На первом месте прописывается индекс – то место, куда должен быть вставлен элемент. Проставим ноль. На втором месте, через запятую, сам элемент. Функция, принимающая два параметра, выглядит так. Результат – число 42 добавлено в начало списка.

-7

Кстати, во время занесения параметров в функцию можно вывести подсказку о том, какой именно параметр сейчас нужно ввести. Это окошко не всегда появляется, но оно вызовется с помощью сочетаний клавиш ctrl + P или cmd + P на маке. Курсор при этом должен находиться внутри скобок, где вводятся параметры метода.

Функция contains()

Следующая функция проверит наличие элемента в списке и вернет Boolean значение true или false. По тому же принципу, как делали это с помощью in в уроке про диапазоны. Сейчас применим метод contains() к списку со значением 42 и получим true. Число 42 содержится в списке mutableList.

-8

Методы isEmpty() и isNotEmpty()

Следующие функции часто пригождаются на практике при создании условий, когда нужно проверять: содержит ли список хоть какой элемент или же он пуст. Это методы isEmpty() и isNotEmpty(). Соответственно методы возвращают значения true или false.

-9

Следующие функции помогут узнать индекс какого-либо элемента, если таковой присутствует в списке. Вызываем метод indexOf() с параметром 42 и получаем индекс 0. Все так. Если одинаковых значений в списке несколько, будет возвращено будет первое, которое встретится. Чтобы узнать последний индекс встречающегося элемента воспользуемся функцией lastIndexOf():

-10

Функции sort() и reverse()

Чтобы отсортировать список есть удобные функции. sort() отсортирует по возрастанию и sortDescending() по убыванию соответственно. Кроме того можно воспользоваться функцией reverse() для изменения порядка элементов в списке на обратный. После применения этих трех методов элементы будут расположены по возрастанию.

-11

Мы еще не изучали лямбды, но еще немного задержимся тут с точки зрения возможностей оформления. Автоматически задекларированную переменную it можно:

  • во-первых: явно прописать, вызвав контекстное меню и выбрав принудительную простановку сигнатуры лямбды,
  • во-вторых: задать произвольное имя переменной, которая будет использоваться внутри тела лямбды. Часто этот прием нужен для повышения читабельности кода. Для этого it меняем на произвольное название и теперь эту переменную можно использовать внутри.

Ок. Очень похоже на принцип работы цикла for, не правда ли? Способ с forEach() выглядит более аккуратным и без дополнительных переменных из-за его стилистики функционального программирования. Но есть нюансы, связанные с удобностью и производительностью для списков или интервалов. Просто перечислю результаты наблюдений из которых можно выбрать собственный способ исходя из ситуации:

  • Если используется интервал, следует использовать цикл for.
  • Если используется коллекция, типа списка, то следует использовать forEach.
  • Если есть необходимость использовать операторы continue или break, то удобнее всего делать это в цикле for.

Расскажу еще про пару популярных функций, обязательных к изучению.

Функция filter()

Основная функция для фильтрации коллекций – filter(). Условие задается фигурных скобках, где указывается логическое выражение, которое возвращает true или false. Так как функция не изменяет список, ее можно использовать и с изменяемыми списками.

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

-12

Функция map()

И еще одна полезная функция для коллекций – map(). Используется, если нам нужно взаимодействовать со всеми элементами. Конечно, все это можно сделать в цикле for, но так изящнее и соответствует стилю функционального программирования. Применив функцию map(), можно обойти все элементы списка и записать их преобразования в новый список. Для демонстрации подойдет любая простая операция. Умножим на 2 все элементы из списка mutableList2 – там сейчас содержится два числа 42. Сохраним результат преобразования в новый список mutableList3 и выведем его в консоль:

-13

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

Дополнительные материалы

🔹 Обучающая платформа с ИИ: https://androidsprint.ru

🔹 Интерактивный курс Kotlin Практикум: https://androidsprint.ru/kotlin-praktikum

🔹 Код из всех уроков в телеграм канале: https://t.me/ievetrov

🔹 Сообщество в VK: https://vk.com/ivan.ievetrov