Kotlin android создание списка

Коллекции. List (Списки)

Коллекции в Kotlin используют множество различных интерфейсов: Iterable, Collection, Set, List, MutableIterable, MutableCollection и др.

В Kotlin нет собственных коллекций, только Java-коллекции. Но при этом в Kotlin они обладают более широкими возможностями, используя расширения. Например, вы можете узнать последний элемент списка или найти максимальное значение в коллекции чисел.

Важная особенность — в Kotlin интерфейсы явно разделены на две группы — изменяемые и неизменяемые. Старайтесь всегда использовать неизменяемые коллекции с доступом для чтения. Если вам нужно изменять коллекцию, то тогда выбирайте другой вариант. Здесь не надо путать с var и val. Если вы создадите список для чтения и привяжете его к переменной var, список всё равно нельзя будет изменить после создания.

Для создания различных типов коллекций есть разные функции. После создания узнаем, какой класс соответствует коллекции. Основные приёмы работы с коллекциями показаны у listOf().

У многих функций есть суффиксы To, By, With: associate, associateTo, associateBy, associateByTo, associateWith, associateWithTo.

В некоторых примерах используются объекты класса Cat.

Функции для создания списков. В списках допустимы дубликаты.

listOf()

Неизменяемые списки List создаются через функцию listOf():

Компилятор определяет тип объекта, который должен содержаться в списке, по типам всех значений, переданных при создании. Например, список в нашем примере инициализируется тремя числами, поэтому компилятор создаёт List с типом List . Тип List также можно задать явно:

Если у вас есть изменяемый список, то его можно сконвертировать в список для чтения через toList():

Доступ к отдельному элементу списка можно получить по номеру индекса через квадратные скобки.

Также можно использовать метод get() с указанием номера индекса.

Но у этих способов есть один недостаток — если вы укажете неправильное значение индекса, то получите исключение ArrayIndexOutOfBoundsException. Вы можете избежать проблемы, если будете использовать метод getOrElse() с указанием значения по умолчанию, если выйдете за пределы допустимых значений. В этом случае вам не придётся обрабатывать исключение.

Другой вариант избежать исключения — использовать getOrNull(), который вернёт null при неправильном индексе. Осталось обработать ситуацию.

Размер списка можно узнать через свойство size. Зная размер, можно без опаски пройтись по всем элементам списка.

Пройтись по всем элементам списка можно через for..in.

Функция associate() позволяет получить Map, используя поля класса как ключ и значение. Например, в нашем случае имена станут ключами, а возраст — ассоциированными значениями.

Функция associateTo() — Зададим отображение originalMap, где ключ является строкой, а значением число. Берём список и применяем наше отображение, указывая нужные поля класса (имя и вес).

Умножаем каждый элемент списка на себя при помощи функции map. Функция проходит по каждому элементу, объединяя результаты в новую коллекцию.

Выводим только имена, игнорируя возраст и другие поля класса.

Можно объединить вызовы функций в цепочки. Выводим имена котов, чей возраст больше 5.

Функция flatMap() работает с коллекцией, содержащей коллекции, и возвращает объединённую «плоскую» коллекцию, содержащую все элементы исходных коллекций.

Читайте также:  Samsung galaxy android amoled дисплей

С помощью any и предиката можно узнать, выполняется ли условие хотя бы для одного элемента.

Выражение !any можно заменить на all.

С помощью all и предиката можно узнать, выполняется ли условие для всех элементов.

Выражение !all можно заменить на any.

С помощью none и предиката можно узнать, что ни один из всех элементов не выполняет условие.

count с предикатом позволяет узнать число элементов в списке, которые соответствуют условию.

Не используйте для этой цели цепочку filter.size, так как вы создаёте промежуточную коллекцию, а это накладные расходы. Функция count считает только количество элементов, а не сами элементы.

fold задаёт начальное значение, а потом собирает все значения в списке от первого к последнему.

reduce работает аналогично, только без указания начального значения.

foldRight работает аналогично fold, только значения берутся от последнего к первому.

reduceRight похож на foldRight без указания начального значения.

forEach позволяет пройтись по всем элементам списка.

forEachIndexed работает аналогично, вдобавок мы можем получить индекс позиции и его значение.

max() позволит получить максимальное значение из списка или null при отсутствии элементов. Работает с базовыми типами. Позже в Kotlin 1.4 метод был переименован в maxOrNull().

Функция min() вычисляет минимальное значение из списка или null при отсутствии элементов. Работает с базовыми типами. Позже в Kotlin 1.4 метод был переименован в minOrNull().

maxBy() возвращает первый элемент с наибольшим значением заданной функции или null, если элементов нет. Работает со всеми типами. Аналогичная функция minBy() возвращает первый элемент с наименьшим значением.

Выберем самого старшего кота.

Функция maxWith() позволяет использовать Comparator. Выберем кота с самым длинным именем.

Кота с самым коротким именем можно вычислить через похожую функцию minWith().

В Kotlin 1.4 появилась новая функция, вычисляющая наибольшее или наименьшее число.

Она удобна при работе с классами для выборки одного поля. Вычислим самого молодого котика.

sumBy() подсчитывает сумму всех элементов, после того, как они подверглись изменению.

При работе с числами Double используйте функцию sumByDouble().

В Kotlin 1.4 появилась новая функция sumOf(), позволяющая суммировать элементы разных типов. Сложим возраст (Int) и вес (Double) всех котов.

Также появились minOfWith() и maxOfWith(), работающие с компаратором.

drop() отсекает указанное число элементов. Также есть функции dropWhile, dropLastWhile.

take оставит первые элементы списка. takeLast оставит последние элементы.

takeWhile оставит первые элементы, которые соответствуют условию.

Соответственно, takeLastWhile() оставит последние элементы, соответствующие условию.

Обратите внимание на разницу между takeWhile() и filter() (см. ниже). Первая функция будет отбирать элементы, пока выполняется условие и прервётся, а вторая пройдётся по всему списку до конца.

takeIf() будет выбирать элементы, если выполняется условие (предикат).

Обратная ситуация — выбирать элементы, если не выполняется условие (предикат).

filter вернёт список, который соответствует предикату. Функция может удалять элементы из коллекции, но не может изменять их (используйте map).

filterNot вернёт список, который не соответствует предикату.

filterNotNull вернёт новый список, не содержащий null.

Расширенная версия filterNotNullTo() уберёт все элементы null и добавит оставшиеся элементы в новый список.

contains() позволит убедиться, что нужный элемент присутствует в списке.

Читайте также:  Поменять курсор мыши андроид

Если нужно проверить сразу несколько элементов, то используйте containsAll(), передавая ему список желаемых элементов.

Получить элемент по индексу можно через elementAt(). Также доступны elementAtOrElse, elementAtOrNull.

first() вернёт первый элемент, соответствующий предикату. Если элемент не будет найдет, то получим исключение NoSuchElementException. Похожая функция firstOrNull вернёт null, если элемент не будет найден.

По такому же принципу работают last() и lastOrNull() для последнего элемента.

find похож на first.

indexOf() вернёт индекс элемента. Функции indexOfFirst(), indexOfLast, lastIndexOf() работают с предикатами.

Функция single() вернёт один уникальный элемент из списка. Если элементов, соответствующих условию, будет несколько будет исключение. singleOrNull вместо исключения вернёт null.

Развернуть элементы списка можно через reverse() и reversed().

Сортировка: sort, sorted, sortedDescending, sortBy, sortByDescending, sortWith

Сортировка оригинального списка происходит через sort().

Отсортировать список можно через sorted(). Возвращается новый список, а оригинальный список остаётся без изменений.

В обратном порядке от большого к меньшему можно через sortedDescending(). Возвращается новый список, а оригинальный список остаётся без изменений.

Сортировка по условию. Отсортируем по именам котов при помощи sortBy().

Аналогично в обратном порядке через sortByDescending().

Если элементы содержат null, то можно сортировать при помощи sortWith() в связке с nullFirst().

Обратная задача решается при помощи nullLast.

Можно сортировать, сравнивая несколько полей класса. Порядок важен. Будем сортировать по имени и по возрасту (имена и возраст могут совпадать в списке).

Сортируем по длине имён в порядке возрастания, используя Comparator.

Если в порядке убывания, то поменяем местами аргументы.

Можно сложить два списка. К элементам первого списка будут добавлены элементы второго списка.

Добавить ещё один элемент можно через plus(). Оригинальный список останется без изменений и будет создан новый список.

Функция minus() отнимает указанный элемент.

Функция average() подсчитывает среднее значение всех элементов списка.

Функция slice возвращает список по указанным индексам.

Функция shuffled() создаёт новый список с перемешанными элементами от старого списка.

Функция shuffle() (Kotlin 1.2) перемешивает элементы изменяемого списка в случайном порядке.

Разбить список на отдельные элементы с определённым условием можно через функцию partition. При значении true элементы попадают в одну группу, а остальные в другую. Возвращается объект Pair, содержащий два списка.

Разделим котов на молодых и пожилых.

groupBy группирует значения по некоторому критерию. Например, мы хотим разбить список котов по возрасту.

На выходе получается словарь с ключами (Map >), которые определяют признак группировки (в нашем случае это возраст). Мы получили одну группу котов с возрастом 5 лет и вторую группу с возрастом 9 лет. Вы можете изменить словарь при помощи mapKeys и mapValues.

Список может содержать дубликаты. Но если вы хотите избавиться от них, то можно преобразовать список во множество, а затем снова в список. Существует готовая функция distinct(), которая сделает это за вас.

Можно задать более точный критерий — например, ищем дубликаты по имени или по возрасту через distinctBy().

Можно даже создать сразу несколько условий для поиска дубликатов. Например, поищем дубликаты и по имени и по возрасту. Пусть у нас будет целая орава котов с одинаковыми именами. Некоторые из них могут быть одного возраста. Вес тоже может совпадать, но пока он нас не интересует.

Читайте также:  Как считывать qr код android sony

emptyList()

Пустой неизменяемый список можно создать через emptyList(), который вернёт тип List.

listOfNotNull()

Ещё один вид неизменяемых списков — listOfNotNull(). Вы можете поместить в список null, но они будут отсечены.

arrayListOf()

Изменяемый список создаётся через arrayListOf(), который возвращает ArrayList.

Сделаем обход коллекции с использованием индекса.

mutableListOf()

Изменять данные можно только в изменяемых списках. Но если у вас есть в наличии неизменяемый список, то его можно сконвертировать в изменяемый через специальный метод toMutableList(). При этом будет создан новый список.

А можно сразу создать изменяемый список нужного типа через mutableListOf (). Также есть перегруженная версия без указания нужного типа — mutableListOf().

При изменении списков индексы пересчитываются.

Удалить элемент из изменяемого списка можно через removeIf(), указав лямбда-выражение в качестве условия.

Удалить все элементы, которые подчиняются условию, можно также через removeAll():

Если надо не удалить, а оставить элементы по определённому условию, то используйте функцию retainAll().

Операции с двумя списками

С помощью addAll() можно добавить в список элементы другого списка.

Другой способ — функция plusAssign():

Вычитать элементы одного списка при помощи элементов другого списка можно через minusAssign().

Ещё один способ объединения двух списков с сохранением только уникальных элементов через union(). Обратите внимание на порядок сохранения — сначала берутся элементы основного списка, а затем добавляются элементы добавляемого списка.

Функция-комбинатор zip() принимает разные коллекции и объединяют их в одну новую. Для примера объединим два списка: с именами котов и их размерами. Функция zip() возвращает новый список (коллекцию пар Pair). Для этой коллекции пар вызовем функцию toMap(), чтобы получить ассоциативный массив, к элементам которого можно обращаться по ключу. В этом случае ключ — имя кота.

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

Попробуем вычитать элементы из списка.

Допустим и такой вариант.

Интересный случай с использованием += и -=. В этом случае следует использовать var, так как мы изменяем список.

replaceAll (Kotlin 1.2)

Заменяет каждый элемент списка новым значением в результате заданного выражения. Доступно для API 24 и выше

fill (Kotlin 1.2)

Заменяет все элементы списка заданным значением.

Все коллекция являются стандартными и полностью совместимыми с Java, Kotlin не использует собственных коллекций, но тем не менее предлагает удобные методы из коробки. Выше были показаны примеры для списков. Можно применять методы для других коллекций.

Например, найдём последний элемент из коллекции.

joinToString()

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

Функция использует параметры по умолчанию, поэтому часть параметров можно опускать.

Создать список из случайных чисел

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

ArrayDeque (Kotlin 1.3.70)

Упражнения для коллекций

Имеется список, некоторые элементы которого повторяются несколько раз. Найти самый повторяемый элемент.

Источник

Оцените статью