Если в сферу ваших интересов входит разработка приложений под Android или мультиплатформенная разработка на Kotlin, то есть все шансы, что вы уже сталкивались с коллекциями в Kotlin.
Kotlin располагает исчерпывающим набором инструментов для работы с коллекциями. Коллекции состоят из элементов одного типа и широко используются в большинстве языков программирования.
Понимание структуры коллекций в Kotlin и способов их эффективного использования при разработке приложений критически важно для полного освоения этого языка программирования и его возможностей.
В этой статье я расскажу вам о Map
в Kotlin, а также о ее использовании и ассоциировании на примерах кода.
Коллекции в Kotlin
Используя коллекции, вы можете хранить, обновлять, извлекать и агрегировать данные. Стандартная библиотека Kotlin предоставляет исчерпывающий набор инструментов для управления коллекциями.
По умолчанию коллекции в Kotlin доступны только для чтения. Вы не можете изменить содержимое такой коллекции, вам необходимо создать новую коллекцию с нужными вам изменениями, которую затем можно безопасно перемещать в приложении, в то время как старая коллекция остается неизменной.
Коллекции Kotlin подразделяются на два вида:
Неизменяемые (Immutable) коллекции.
Изменяемые (Mutable) коллекции.
В Kotlin есть следующие типы коллекций:
List
: упорядоченный список с доступом к элементам по индексам. (Примечание: элементы в списке могут дублироваться).Set
: набор (множество) уникальных элементов, т.е. это группа объектов без дублирований.Map
: набор пар ключ-значение. Ключи уникальны, и каждый из них соответствует ровно одному значению.
Кроме того, в Kotlin также есть изменяемые варианты этих коллекций: MutableList, MutableSet и MutableMap, которые позволяют разным образом модифицировать коллекцию, например добавлять или удалять элементы.
Изменяемые типы приходят на выручку, когда необходимо часто манипулировать данными в соответствии с какими-либо требованиями; хорошим примером этого могут быть результаты вызовов API, отображаемые в виде списка с фильтрами или поисковыми запросами.
Введение в Map в Kotlin
Map
также известны как словари или ассоциативные массивы в других языках программирования. Map
в Kotlin по умолчанию неизменяемы. Это означает, что после создания элемента в Map
его нельзя редактировать, удалять или обновлять.
Однако Kotlin позволяет пользователям создавать изменяемые map, которые можно изменить после их создания. Если вы хотите создать изменяемую map, вы должны использовать соответствующий изменяемый тип.
Чтобы использовать интерфейс Map
в Kotlin, вам нужно задействовать его функции mapOf()
или mapOf<k,v>()
.
Ниже приведен пример создания Map:
val peopleToCarsOwned = mapOf(
"Jack" to "Mercedes",
"John" to "Audi",
"Will" to "Jaguar"
)
println(peopleToCarsOwned)
// Это выведет следующее:
// {Jack=Mercedes, John=Audi, Will=Jaguar}
println(carsOwned["John"])
// Это выведет следующее:
// Audi
Являющиеся основой Map
данные типа пар ключ-значение широко используются в Kotlin. Таким образом, Map
является одним из основных способов управления структурированными данными в Kotlin.
Map располагает рядом функций, которые можно использовать для обработки данных и получения различных результатов. Давайте рассмотрим несколько функций общего назначения.
Получение данных
Возможность получать доступ к парам ключ-значение имеет решающее значение для работы с Map
. Для получения ключей и значений используются привычные для всех get-методы. Метод getKey используется для получения значения указанного ключа. Если ключа не существует, будет возвращен null
.
Метод getValue
возвращает значением ключ, связанное с предоставленным ключом. Однако, для случаев когда ключ, указанный в этой get-функции, может не иметь связанного значения, у нас есть несколько вариаций getValue
.
В таких случаях можно использовать методы getOrElse
и getOrDefault
. Для случаев, когда ключ не найден, getOrDefault
позволяет указать значение по умолчанию, а getOrElse
позволяет указать функцию, результат которой будет возвращен.
Фильтрация данных
При использовании Map бывает очень полезно фильтровать данные для поиска конкретной информации и доступа к парам ключ-значение. Как и другие коллекции в Kotlin, Map можно фильтровать с помощью filter.
FilterKey
и filterValue
аналогичны get-методам, поскольку они позволяют фильтровать по ключу или значению. При применении фильтра возвращается новая Map
с отфильтрованными элементами. Если вы используете filterKey
, вы получите Map
, полностью состоящую из указанных ключей.
Давайте посмотрим на пример ниже:
open class Car(val name: String, val manufacturedIn: Int) {
override fun toString() = name
}
val cars = mapOf(
"Aston Martin" to 2015,
"Lamborghini" to 2000,
"BMW" to 1990,
"Mercedes Benz" to 1980
)
val newCars = cars.filter {
it.manufacturedIn >= 2000
}
println(newCars)
// Это выведет следующее: [Aston Martin, Lamborghini]]
Если вам нужно отфильтровать все данные, которые наоборот удовлетворяют конкретному условию, то можно использовать filterNot
, которая используется аналогично filter как показано ниже:
// Kotlin
val oldCars = cars.filterNot {
it.age >= 2000
}
println(oldCars)
// Это выведет следующее: [BMW, Mercedes Benz]
Редактирование данных
Так как Map
по умолчанию неизменяема, то вам необходимо изначально создавать изменяемую Map
, если вы планируете вносить изменения в Map
. Также стоит отметить, что ключи изменять нельзя, но их можно удалять — вы изменяете значение ключа при редактировании записи.
Вы можете создавать новые комбинации пар ключ-значение, обновлять значение существующего ключа или полностью удалять конкретные пары ключ-значение. Чтобы добавить новые данные в Map
Kotlin вам нужно использовать метод put
.
Однако если введенный вами ключ уже существует в вашей Map
, вы можете использовать put
для замены уже существующего значения для этого ключа. Удалять элементы из вашей Map
вы можете с помощью метода remove
.
Работа с Map в Kotlin
Чтобы лучше понять, как работает интерфейс Map
в Kotlin, мы рассмотрим пару распространенных сценариев на примерах ниже:
val genericMap: Map<Int, String> = mapOf<Int,String>(
1 to "Jack",
4 to "John",
3 to "Will"
)
for(key in genericMap.keys) {
println("Element at key position $key: ${genericMap.get(key)}")
}
// Это выведет следующее:
// Element at key position 1: Jack
// Element at key position 4: John
// Element at key position 3: Will
Вы можете указать любую комбинацию ключей и значений для Map
. Это возможно, потому что под капотом Map
использует объявление <Any, Any>
. Взгляните на этот пример:
val customMap = mapOf(
1 to "Rick",
4 to "Tesla",
3 to True,
"Train" to "Station",
"Rocket" to "Launch"
)
for(key in customMap.keys) {
println("Element at key position $key: ${customMap.get(key)}")
}
// Это выведет следующее:
// Element at key position 1: Rick
// Element at key position 4: Tesla
// Element at key position 3: True
// Element at key position Train: Station
// Element at key position Rocket: Launch
Заключение
Несмотря на то, что глубокое понимание того, как работает Map
в Kotlin, вряд ли нужно, чтобы улучшить ваше приложение, базовое понимание однако имеет ключевое значение.
Такие структуры данных необходимы для реализации множества фич, которые пользователи привыкли ожидать от современных мобильных приложений.
Приглашаем всех желающих на открытое занятие «Разработка монолитного приложения со Spring». На занятии мы:
Познакомимся со Spring фреймворком и его принципом работы.
Рассмотрим особенности разработки Spring приложения на языке Kotlin.
Разработаем монолитное приложение и напишем пару интеграционных тестов.
Упакуем наше приложение в Docker, как готовое решение.
Plesser
это не рабочий пример (как cars связано с Car?), возможно для знатоков котлин тут все понятно но вот для тех кто не является им....
Prototik
Никак не связано, Car действительно никак не используется.
Если mapOf заменить на listOf<Car> - тогда рабочий.
А с мапой оно ещё и не работает по причине того, что в filter приходит Map.Entry, в котором лежит key и value, но содержимое фильтра клало на эту мааааленькую недоработку. Хоть бы в IDE код бы вставили, такие уж глупости они бы не пропустила...