Как добавить элемент в список kotlin
На этом шаге мы рассмотрим способы изменения содержимогосписка .
Если посетитель пришел или ушел в середине ночи, внимательный трактирщик должен добавить или убрать имя посетителя из переменной patronList . В настоящее время это невозможно.
Функция listOf() возвращает список, доступный только для чтения, в котором нельзя менять содержимое: вы не сможете добавить, убрать, обновить или заменить данные. Доступные только для чтения списки — хорошее решение, потому что они предотвращают досадные ошибки, например, возможность выгнать посетителя на улицу, убрав его имя из списка случайно.
Природа доступа только для чтения у списка не имеет ничего общего с ключевым словом val или var , использованным для объявления переменной списка. Заменив в объявлении переменной patronList c val (как сейчас) на var , вы не сделаете список доступным для изменения. Вам просто будет разрешено присвоить переменной patronList другое значение, то есть создать новый список.
Возможность изменять список напрямую зависит от его типа, который и определяет возможность изменять элементы в списке. Поскольку посетители постоянно приходят и уходят, мы должны изменить тип patronList , чтобы разрешить обновление. В языке Kotlin модифицируемый список известен как изменяемый список , и вы должны вызвать функцию mutableListOf() , чтобы его создать.
Измените код Tavern.kt и используйте mutableListOf() вместо listOf() . Изменяемые списки поддерживают множество функций для добавления, удаления и обновления содержимого. Смоделируйте приход и уход нескольких посетителей, использовав функции add() и remove() .
import kotlin.math.roundToInt const val TAVERN_NAME = "Taernyl's Folly" var playerGold = 10 var playerSilver = 10 val patronList = mutableListOf("Eli", "Mordoc", "Sophie") fun main() < . . . . placeOrder("shandy,Dragon's Breath,5.91") println(patronList) patronList.remove("Eli") patronList.add("Alex") println(patronList) > . . . .
Файл с проектом можно взять здесь.
Рис.1. Создание изменяемого списка посетителей (Tavern.kt)
Запустите Tavern.kt . В консоли появится следующее сообщение:
Madrigal exclaims Ah, d3l1c10|_|s Dr4g0n's Br34th! [Eli, Mordoc, Sophie] [Mordoc, Sophie, Alex]
Рис.2. Результат работы приложения
Возможность изменять список напрямую зависит от его типа, который и определяет возможность изменять элементы в списке. Если нужно изменить элементы в списке, используйте MutableList . В противном случае хорошим решением будет запретить изменяемость, используя обычный список.
Обратите внимание, что новый элемент был добавлен в конец списка. Можно добавить посетителя в конкретное место списка. Например, если VIP -гость придет в таверну, трактирщик может отдать ему предпочтение в очереди.
Добавьте VIP -гостя — пусть это будет посетитель с таким же именем Алекс ( Alex ) — в начало списка посетителей. (Алекс хорошо известен в городе и пользуется такими привилегиями, как покупка пинты Dragon’s Breath раньше всех остальных, что, конечно, не нравится другому Алексу.) Список может содержать несколько элементов с одинаковым значением, как, например, два посетителя с одинаковыми именами, поэтому добавление еще одного Алекса — это не проблема для списка.
. . . . fun main() < . . . . placeOrder("shandy,Dragon's Breath,5.91") println(patronList) patronList.remove("Eli") patronList.add("Alex") patronList.add(0, "Alex") println(patronList) > . . . .
Файл с проектом можно взять здесь.
Рис.3. Добавление еще одного Alex (Tavern.kt)
Запустите Tavern.kt снова. Вы увидите следующий вывод:
[Eli, Mordoc, Sophie] [Alex, Mordoc, Sophie, Alex]
Рис.4. Результат работы приложения
Чтобы сделать список patronList изменяемым, нам пришлось заменить в своем коде listOf() на mutableListOf() . Но List имеет функции, позволяющие превращать неизменяемые списки в изменяемые и обратно прямо в процессе выполнения: toList() и toMutableList() . Например, снова сделайте изменяемый patronList() доступным только для чтения, используя toList() :
val patronList = mutablelistOf("Eli", "Mordoc", "Sophie") val readOnlyPatronList = patronList.toList()
Допустим, популярный Alex решил сменить имя на Alexis . Исполнить его желание можно, изменив patronList при помощи оператора присваивания ([]=), то есть присвоив строке с первым индексом новое значение.
. . . . fun main() < . . . . placeOrder("shandy,Dragon's Breath,5.91") println(patronList) patronList.remove("Eli") patronList.add("Alex") patronList.add(0, "Alex") patronList[0] = "Alexis" println(patronList) > . . . .
Файл с проектом можно взять здесь.
Рис.5. Модифицирование изменяемого списка с помощью оператора присваивания (Tavern.kt)
Запустите Tavern.kt . Вы увидите, что patronList обновился и содержит новое имя Alexis .
[Eli, Mordoc, Sophie] [Alexis, Mordoc, Sophie, Alex]
Рис.6. Результат работы приложения
Функции, которые изменяют содержимое изменяемых списков, называют мутаторами . В таблице 1 перечислены самые распространенные мутаторы для списков.
| Функция | Описание | Примеры |
|---|---|---|
| []= (оператор присваивания) | Присваивает значение по индексу; возбуждает исключение, если индекс не существует | val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList[4] = «Reggie» IndexOutOfBoundsException |
| add | Добавляет элемент в конец списка, увеличивая размер на один элемент | val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList.add(«Reggie») [Eli, Mordoc, Sophie, Reggie] patronList.size 4 |
| add (по индексу) | Добавляет элемент в список по индексу, увеличивая размер на один элемент. Возбуждает исключение, если индекс не существует | val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList.add(0, «Reggie») [Reggie, Eli, Mordoc, Sophie] patronList.add(5, «Sophie») IndexOutOfBoundsException |
| addAll | Добавляет все элементы из другой коллекции, если они того же типа | val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList.addAll(listOf(«Reginald», «Alex»)) [Eli, Mordoc, Sophie, Reginald, Alex] |
| += (оператор сложения с присваиванием) | Добавляет элемент или коллекцию элементов в список | mutableListOf(«Eli», «Mordoc», «Sophie») += «Reginald» [Eli, Mordoc, Sophie, Reginald] mutableListOf(«Eli», «Mordoc», «Sophie») += listOf(«Alex», «Shruti») [Eli, Mordoc, Sophie, Alex, Shruti] |
| -= (оператор вычитания с присваиванием) | Удаляет элемент или коллекцию элементов из списка | mutableListOf(«Eli», «Mordoc», «Sophie») -= «Eli» [Mordoc, Sophie] val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList -= listOf(«Eli», Mordoc») [Sophie] |
| clear | Удаляет все элементы из списка | mutableListOf(«Eli», «Mordoc», Sophie»).clear() [] |
| removeIf | Удаляет все элементы из списка, которые удовлетворяют условию в лямбде | val patronList = mutableListOf(«Eli», «Mordoc», «Sophie») patronList.removeIf < it.contains("o") > [Eli] |
На следующем шаге мы рассмотрим итерацию .
Как добавить элемент в список kotlin
List представляет последовательный список элементов. При этом List представляет неизменяемую (immutable) коллекцию, которая в основном только обеспечивает получение элементов по позиции.
Интерфейс List расширяет интерфейс Collection , поэтому перенимает его возможности.
Для создания объекта List применяется метод listOf() :
var numbers = listOf(1, 2, 3, 4, 5) // объект List val people = listOf(«Tom», «Sam», «Kate», «Bob», «Alice») // объект List
Списки поддерживают перебор с помощью цикла for, кроме для списка по умолчанию задача реализация toString, которая выводит все элементы списка в удобочитаемом виде:
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice") for(person in people) println(person) println(people) // [Tom, Sam, Kate, Bob, Alice]
Методы списков
Кроме унаследованных методов класс List имеет ряд специфичных. Рассмотрим некоторые из них.
Для получения элемента по индексу можно применять метод get(index) , который возвращает элемент по индексу
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice") val first = people.get(0) val second = people.get(1) println(first) // Tom println(second) // Sam
Вместо метода get для обращения по индексу можно использовать квадратные скобки [] :
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice") val first = people[0] val second = people[1] println(first) // Tom println(second) // Sam
Однако, если индекс выходит за границы списка, то при использовании метода get() и квадратных скобок генерируется исключение. Чтобы избежать подобной ситуации, можно применять метод getOrNull() , который возвращает null, если индекс находится вне границ списка:
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice") val first = people.getOrNull(0) val tenth = people.getOrNull(10) println(first) // Tom println(tenth) // null
Либо в качестве альтернативы можно применять метод getOrElse() :
getOrElse(index: Int, defaultValue: (Int) -> T): T
Первый параметр представляет индекс, а второй параметр — функция, которая получает запрошенный индекс и возвращает значение, которое возвращается, если индекс выходит за границы списка:
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice") val first = people.getOrElse(0) val seventh = people.getOrElse(7) val tenth = people.getOrElse(10) println(first) // Tom println(seventh) // Invalid index 7 println(tenth) // Undefined
Получение части списка
Метод subList() возвращает часть списка и в качестве параметров принимает начальный и конечный индексы извлекаемых элементов:
subList(fromIndex: Int, toIndex: Int): List
Например, получим подсписок с 1 по 4 индексы:
val people = listOf("Tom", "Sam", "Kate", "Bob", "Alice", "Mike") val subPeople = people.subList(1, 4) println(subPeople) // [Sam, Kate, Bob]
Изменяемые списки
Изменяемые списки представлены интерфейсом MutableList . Он расширяет интерфейс List и позволяют добавлять и удалять элементы. Данный интерфейс реализуется классом ArrayList .
Для создания изменяемых списков можно использовать ряд методов:
- arrayListOf() : создает объект ArrayList
- mutableListOf() : создает объект MutableList
Создание изменяемых списков:
var numbers : ArrayList = arrayListOf(1, 2, 3, 4, 5) var numbers2: MutableList = mutableListOf(5, 6, 7)
Если необходимо добавлять или удалять элементы, то надо использовать методы MutableList:
- add(index, element) : добавлят элемент по индексу
- add(element) : добавляет элемент
- addAll(collection) : добавляет коллекцию элементов
- remove(element) : удаляет элемент
- removeAt(index) : удаляет элемент по индексу
- clear() : удаляет все элементы коллекции
fun main() < val numbers1 : ArrayList= arrayListOf(1, 2, 3, 4, 5) numbers1.add(4) numbers1.clear() val numbers2: MutableList = mutableListOf(5, 6, 7) numbers2.add(12) numbers2.add(0, 23) numbers2.addAll(0, listOf(-3, -2, -1)) numbers2.removeAt(0) numbers2.remove(5) for (n in numbers2) < println(n) >>
Урок 9: Списки в Kotlin, функции для работы с коллекциями
По определению коллекции – это группы с переменным количеством элементов (или нулем элементов). Объекты внутри как правило имеют единый тип. Коллекции называются коллекциями, потому что корнем их иерархии в языке является класс Collection. Позже, при изучении наследования это станет понятнее, пока не будем сильно углубляться.
Коллекции могут подразделяться на следующие типы:
- List (список) – упорядоченный набор элементов, к ним можно обращаться по индексам. В списке могут встречаться дубликаты.
- Set (множество) – коллекция уникальных элементов. То есть повторяющиеся элементы исключены. Порядок элементов может быть любым.
- Map (словарь или ассоциативным список) – определенный набор пар. Пара содержит в себе ключ и значение. Зная ключ, можно обратиться к какому-нибудь значению. Ключи строго уникальны, а значения могут иметь дубликаты.
В этот раз подробнее остановимся на списках. Поведение напоминает работу с массивами, однако, есть существенные отличия в принципе работы. Вот основные из них:
- Первое. Массив имеет строго фиксированный размер и не может уменьшаться или увеличиваться. Изменить размер массива можно только создав его копию с дополнительными или утраченными элементами. Списки же имеют методы add и remove для добавления/удаления элементов.
- Второе. Массив предоставляется классом Array. List является интерфейсом и имеет разные реализации со своим функционалом.
- Третье. Массивы оптимизированы для примитивов и меют отдельные типа IntArray, CharArray и т.д. Списки такой оптимизации не имеют.
- Четвертое. Различается процесс сравнивания элементов друг с другом. В массивах сравниваются адреса ячеек в памяти, в списках же идет сравнение самого значения.
В целом хорошей практикой считается использовать списки вместо массивов везде, где это позволяет техническая реализация. Однако, с точки зрения производительности, массивы имеют над списками преимущество.
Создание списков в Котлин
Списки создаются с помощью функции listOf() из стандартной библиотеки Kotlin. Короткая запись создания целочисленного списка выглядит так:
val list = listOf(4, 4, 2)
Если принудительно проставить тип списка, получим List. Это базовый интерфейс для всех неизменяемых списков:
val list: List = listOf(4, 4, 2)
Его “неизменяемость” определяется тем, что нельзя просто так взять и обратиться по индексу к элементу и заменить его на другой. Как мы делали это с массивами. Также отсутствуют функции по добавлению и удалению элементов.
Изменяемые списки в Kotlin
В таких списках мы можем читать конкретное значение по индексу, а также пробегать циклом по всем значениям вместе. Но для того, чтобы создать изменяемый список, необходимо использовать функцию mutableListOf().
При данной инициализации тип переменной будет MutableList . Это второй базовый интерфейс для списков, на основе которого создаются изменяемые списки. Это List с возможностью добавления или удаления элементов:
val list3: MutableList = mutableListOf(1, 2, 3)
Функции для работы со списками
Теперь переходим к инструментарию по работе со списками. В уроке примеры будут представлены на примере целочисленного списка. А в практике, прилагаемой к уроку, будут оформлены задачи с применением различных типов с неким прикладным контекстом.
Еще раз создадим изменяемый список с некоторым количеством чисел.
val mutableList = mutableListOf(11, 15, 20, 12, 9, 14)
Сначала будем добавлять значения в список с помощью функции add(). Чтобы воспользоваться ей, необходимо написать переменную со списком и вызвать для нее этот метод с помощью обращения через точку.
Метод add() может принимать два набора параметров и в зависимости от этого, будет произведены разные действия.
Первый вариант – это всего один параметр, который является новым элементом, который нужно добавить в список. Этот элемент по умолчанию добавляется в конец списка. Результат в консоли:
val mutableList = mutableListOf(11, 15, 20, 12, 9, 14) println(mutableList) mutableList.add(42) println(mutableList)
Второй вариант – это когда метод add() принимает два параметра. На первом месте прописывается индекс – то место, куда должен быть вставлен элемент. Проставим ноль. На втором месте, через запятую, сам элемент. Функция, принимающая два параметра, выглядит так. Результат – число 42 добавлено в начало списка.
mutableList.add(0, 42) println(mutableList)
Кстати, во время занесения параметров в функцию можно вывести подсказку о том, какой именно параметр сейчас нужно ввести. Это окошко не всегда появляется, но оно вызовется с помощью сочетаний клавиш ctrl + P или cmd + P на маке. Курсор при этом должен находиться внутри скобок, где вводятся параметры метода.
Следующая функция проверит наличие элемента в списке и вернет Boolean значение true или false. По тому же принципу, как делали это с помощью in в уроке про диапазоны. Сейчас применим метод contains() к списку со значением 42 и получим true. Число 42 содержится в списке mutableList.
println(mutableList.contains(42))
Следующие функции часто пригождаются на практике при создании условий, когда нужно проверять: содержит ли список хоть какой элемент или же он пуст. Это методы isEmpty() и isNotEmpty(). Соответственно методы возвращают значения true или false.
println(mutableList.isEmpty()) println(mutableList.isNotEmpty())
Следующие функции помогут узнать индекс какого-либо элемента, если таковой присутствует в списке. Вызываем метод indexOf() с параметром 42 и получаем индекс 0. Все так. Если одинаковых значений в списке несколько, будет возвращено будет первое, которое встретится. Чтобы узнать последний индекс встречающегося элемента воспользуемся функцией lastIndexOf():
println(mutableList.indexOf(42)) println(mutableList.lastIndexOf(42))
Функция sort
Чтобы отсортировать список есть удобные функции. sort() отсортирует по возрастанию и sortDescending() по убыванию соответственно. Кроме того можно воспользоваться функцией reverse() для изменения порядка элементов в списке на обратный. После применения этих трех методов элементы будут расположены по возрастанию.
mutableList.forEach
Мы еще не изучали лямбды, но еще немного задержимся тут с точки зрения возможностей оформления. Автоматически задекларированную переменную it можно:
- во-первых: явно прописать, вызвав контекстное меню и выбрав принудительную простановку сигнатуры лямбды,
- во-вторых: задать произвольное имя переменной, которая будет использоваться внутри тела лямбды. Часто этот прием нужен для повышения читабельности кода. Для этого it меняем на произвольное название и теперь эту переменную можно использовать внутри.
Ок. Очень похоже на принцип работы цикла for, не правда ли? Способ с forEach() выглядит более аккуратным и без дополнительных переменных из-за его стилистики функционального программирования. Но есть нюансы, связанные с удобностью и производительностью для списков или интервалов. Просто перечислю результаты наблюдений из которых можно выбрать собственный способ исходя из ситуации:
- Если используется интервал, следует использовать цикл for.
- Если используется коллекция, типа списка, то следует использовать forEach.
- Если есть необходимость использовать операторы continue или break, то удобнее всего делать это в цикле for.
Расскажу еще про пару популярных функций, обязательных к изучению.
Функция filter()
Основная функция для фильтрации коллекций – filter(). Условие задается фигурных скобках, где указывается логическое выражение, которое возвращает true или false. Так как функция не изменяет список, ее можно использовать и с изменяемыми списками.
Напишем этот пример. Отфильтрованный список будет помещен в новую переменную. В фигурных скобках пишем условие. it (элемент коллекции) равен, например, 42. Ниже сделаем вывод нового списка через forEach(). Таким образом каждый элемент будет проверяться на равенство с числом 42 и если оно верно, элемент запишется в новый список.
val mutableList2 = mutableList.filter < it == 42 >mutableList2.forEach
Функция map()
И еще одна полезная функция для коллекций – map(). Используется, если нам нужно взаимодействовать со всеми элементами. Конечно, все это можно сделать в цикле for, но так изящнее и соответствует стилю функционального программирования. Применив функцию map(), можно обойти все элементы списка и записать их преобразования в новый список. Для демонстрации подойдет любая простая операция. Умножим на 2 все элементы из списка mutableList2 – там сейчас содержится два числа 42. Сохраним результат преобразования в новый список mutableList3 и выведем его в консоль:
val mutableList3 = mutableList2.map < it * 2 >println(mutableList3)
Далее на практике написания приложений мы часто будем сталкиваться с функциями-расширениями и даже научимся создавать свои. Сейчас это все, что я хотел сказать по стандартным функциям для коллекций.
Для тех, кто собрался стать Android-разработчиком
Пошаговая
схема
Описание процесса обучения от основ Kotlin до Android-разработчика
Бесплатные
уроки
Авторский бесплатный курс по основам языка программирования Kotlin
Обучающий
бот
Тренажер и самоучитель по Котлин – бесплатные тесты и практика
Операции записи коллекций
Изменяемые коллекции поддерживают операции, изменяющие её содержимое, например, операции по добавлению и удалению элементов. В этом разделе описаны операции записи, доступные для всех реализаций MutableCollection . Более конкретные операции, доступные для List и Map , описаны в разделах List: специфичные операции и Map: специфичные операции.
Добавление элементов
Чтобы добавить один элемент в список или множество ( Set ), используйте функцию add() . Указанный объект будет добавлен в конец коллекции.
fun main() < val numbers = mutableListOf(1, 2, 3, 4) numbers.add(5) println(numbers) // [1, 2, 3, 4, 5] >
Функция addAll() добавляет все элементы из переданного в качестве аргумента объекта в список или множество. Аргументом может быть Iterable , Sequence , или Array . Типы объекта-получателя и аргумента могут быть разными, например, вы можете добавить все элементы из Set в List .
При вызове к списку addAll() добавляет новые элементы в том же порядке, в котором они находятся в коллекции-аргументе. Вы также можете передать addAll() позицию, в которую будет вставлен первый элемент из коллекции-аргумента. За ним последуют другие элементы из коллекции-аргумента, сдвигая элементы коллекции-получателя в конец.
fun main() < val numbers = mutableListOf(1, 2, 5, 6) numbers.addAll(arrayOf(7, 8)) println(numbers) // [1, 2, 5, 6, 7, 8] numbers.addAll(2, setOf(3, 4)) println(numbers) // [1, 2, 3, 4, 5, 6, 7, 8] >
Вы также можете добавлять элементы, используя in-place версию оператора plus — plusAssign ( += ). При применении к изменяемой коллекции += добавляет второй операнд (элемент или другую коллекцию) в конец коллекции.
fun main() < val numbers = mutableListOf("one", "two") numbers += "three" println(numbers) // [one, two, three] numbers += listOf("four", "five") println(numbers) // [one, two, three, four, five] >
Удаление элементов
Чтобы удалить элемент из изменяемой коллекции, используйте функцию remove() . Она принимает значение элемента в качестве аргумента и удаляет из коллекции одно вхождение этого значения.
fun main() < val numbers = mutableListOf(1, 2, 3, 4, 3) numbers.remove(3) // удаляет только первое значение `3` println(numbers) // [1, 2, 4, 3] numbers.remove(5) // ничего не удаляет println(numbers) // [1, 2, 4, 3] >
Для одновременного удаления нескольких элементов существуют следующие функции:
- removeAll() — удаляет все элементы, присутствующие в коллекции-аргументе. В качестве альтернативы вы можете вызвать её с предикатом; в этом случае функция удаляет все элементы, для которых предикат возвращает true .
- retainAll() — противоположность removeAll() : удаляет все элементы кроме тех, что находятся в коллекции-аргументе. При использовании с предикатом она оставляет только те элементы, которые ему соответствуют.
- clear() — удаляет все элементы из списка, оставляя его пустым.
fun main() < val numbers = mutableListOf(1, 2, 3, 4) println(numbers) // [1, 2, 3, 4] numbers.retainAll < it >= 3 > println(numbers) // [3, 4] numbers.clear() println(numbers) // [] val numbersSet = mutableSetOf("one", "two", "three", "four") numbersSet.removeAll(setOf("one", "two")) println(numbersSet) // [three, four] >
Еще один способ для удаления элементов из коллекции — оператор minusAssign ( -= ) — это in-place версия оператора minus . Второй аргумент может быть либо одним элементом, либо другой коллекцией. Если второй аргумент — это элемент, то оператор -= удалит первое вхождение этого элемента. Если же второй аргумент — это коллекция, то будут удалены все вхождения её элементов. Например, если список содержит повторяющиеся элементы, то они все будут удалены. Второй операнд может содержать элементы, которых нет в коллекции. Такие элементы не влияют на выполнение операции.
fun main() < val numbers = mutableListOf("one", "two", "three", "three", "four") numbers -= "three" println(numbers) // [one, two, three, four] numbers -= listOf("four", "five") //numbers -= listOf("four") // делает то же самое, что и выше println(numbers) // [one, two, three] >
Обновление элементов
Списки и ассоциативные списки также предоставляют операции для обновления элементов. Они описаны в разделах List: специфичные операции и Map: специфичные операции. Для Set обновление элементов не имеет смысла, поскольку фактически он удаляет элемент и добавляет другой.
© 2015—2023 Open Source Community