Освой Kotlin играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Ассоциативные списки с уникальными ключами и любыми значениями (дубликаты ключей не допускаются, значения могут быть одинаковыми). Связь между ключами и значениями происходит через специальную форму вызова метода (инфиксный вызов) to.
Неизменяемый Map создаётся через mapOf(). Вы не можете добавлять или удалять пару ключа и значения или обновлять значение в ключе:
val map = mapOf(1 to "one", 3 to "three", 9 to "nine")
println(map.javaClass) // class java.util.LinkedHashMap
Другой способ создания через Pair.
val map = mapOf(Pair(1, "one"), Pair(3, "three"), 9 to "nine") // оставлен один вариант через to
Вывести содержимое коллекции можно через вызов самой переменной.
println(map)
{1=one, 3=three, 9=nine}
В примере ключи были числами, а значения строками. Можно сделать наоборот, ключи будут строками, а значения числами.
val map = mapOf("One" to 1, "Two" to 2, "Eight" to 8)
// равносильно val map: Map<String, Int> = mapOf("One" to 1, "Two" to 2, "Eight" to 8)
println(map)
Проверить существование ключа или значения можно через containsKey() и containsValue().
map.containsKey("One")
Получить значение у заданного ключа можно через get() или getValue(). Если указать несуществующий ключ, то get() вернёт null, а getValue() выбросит исключение NoSuchElementException. Также можно получить значение ключа через квадратные скобки.
val map = mutableMapOf("One" to 1, "Two" to 2, "Three" to 3)
println(map.getValue("One"))
println(map["Two"])
Во избежание проблем с исключениями применяйте getOrElse() или getOrDefault().
// анонимная функция для несуществующего ключа
val map = mapOf("One" to 1, "Two" to 2, "Eight" to 8)
val number = map.getOrElse("One1") {"No such number"}
println(number)
// Значение по умолчанию
val map = mapOf("One" to 1, "Two" to 2, "Eight" to 8)
val number = map.getOrDefault("Cat", 0)
println(number)
Перебрать все ключи и их значения можно в цикле for.
val map = mapOf("One" to 1, "Two" to 2, "Three" to 3)
for((key, value) in map){
println("Key is $key, value is $value")
}
А можно через функцию forEach().
val map = mapOf("One" to 1, "Two" to 2, "Three" to 3)
map.forEach{entry ->
println("Значение ${entry.value} у ключа ${entry.key}")
}
Значение 1 у ключа One
Значение 2 у ключа Two
Значение 3 у ключа Three
Применим функцию отбора и преобразования.
val map = mapOf(1 to "one", 3 to "three", 9 to "nine")
println(map.mapValues { it.value.toUpperCase() })
{1=ONE, 3=THREE, 9=NINE}
Изменяемый Map.
val currenciesMutableMap: MutableMap<String, String> =
mutableMapOf("Гривна" to "Украина", "Доллар" to "США", "Рубль" to "Россия")
println("Страны: ${currenciesMutableMap.values}") // Страны: [Украина, США, Россия]
println("Валюты: ${currenciesMutableMap.keys}") // Валюты: [Гривна, Доллар, Рубль]
currenciesMutableMap.put("Тугрик", "Монголия")
currenciesMutableMap.remove("Доллар")
println(currenciesMutableMap) //{Гривна=Украина, Рубль=Россия, Тугрик=Монголия}
Так как мы имеем дело с изменяемым Map, то у него есть дополнительные возможности. Например, мы можем добавить новую запись через put().
val map = mutableMapOf("One" to 1, "Two" to 2, "Three" to 3)
map.put("Four", 4)
println(map)
Можно добавить через оператор +=. Если ключ уже существует, то его значение будет переписано.
val map = mutableMapOf("One" to 1, "Two" to 2, "Three" to 3)
map.put("Four", 4)
map += "Five" to 5
map += "Two" to 22
println(map) //{One=1, Two=22, Three=3, Four=4, Five=5}
Можно сначала подготовить несколько записей для вставки и вставить их сразу через putAll():
val map = mutableMapOf("One" to 1, "Two" to 2, "Three" to 3)
val entry1 = Pair("Four", 4)
val entry2 = Pair("Five", 5)
val entryToAdd = mapOf(entry1, entry2)
map.putAll(entryToAdd)
println(map)
Объединить две коллекции можно также через putAll().
val mapA = mutableMapOf<String, Int>("a" to 1, "b" to 2)
val mapB = mutableMapOf<String, Int>("a" to 2, "d" to 4)
mapA.putAll(mapB)
println(mapA) // {a=2, b=2, d=4}
При совпадении ключей побеждает более поздний вызов, поэтому ключ из mapB перепишет ключ из mapA.
Удалить запись можно по ключу через remove():
map.remove("Two")
Перегруженная версия remove() удалит запись только при совпадении ключа и его значения.
val map = mutableMapOf("One" to 1, "Two" to 2, "Three" to 3)
val entry1 = Pair("Four", 4)
val entry2 = Pair("Five", 5)
val entryToAdd = mapOf(entry1, entry2)
map.putAll(entryToAdd)
map.remove("Two", 3) // не удалит
map.remove("Five", 5) // удалит
println(map)
Очистить все записи можно через clear(). Но сам объект остаётся.
Можно перевести в список List через toList().
val list = map.toList()
println(list)
//[(One, 1), (Two, 2), (Three, 3), (Four, 4), (Five, 5)]
Изменяемый HashMap.
//val personsHashMap: java.util.HashMap<Int, String> =
// hashMapOf(1 to "Барсик", 2 to "Мурзик", 3 to "Рыжик")
val personsHashMap = hashMapOf(1 to "Барсик", 2 to "Мурзик", 3 to "Рыжик")
personsHashMap.put(4, "Васька")
personsHashMap.remove(2)
println(personsHashMap[1])
Получить значение по ключу можно через метод getOrDefault() (относится к Java 8). Если ключ не будет найден, то подставится значение по умолчанию.
fun byName(name: String): String =
map.getOrDefault(name, "cat")
private val map: Map<String, String> = hashMapOf(
"one" to "value one",
"two" to "value two",
"three" to "value three"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
println(byName("one"))
// укажем несуществующий ключ
println(byName("barsik"))
}
Если вынуждены использовать Java 7, то используйте квадратные скобки и элвис-оператор.
fun byName(name: String): String = map[name] ?: "cat"
Изменяемый LinkedHashMap.
val postalHashMap: java.util.LinkedHashMap<String, String> =
linkedMapOf("NG" to "Nigeria","AU" to "Australia","CA" to "Canada")
postalHashMap.put("NA", "Namibia")
postalHashMap.remove("AU")
postalHashMap.get("CA") // Canada
Изменяемый SortedMap, сортировка по ключу.
val personsSortedMap: java.util.SortedMap<Int, String> =
sortedMapOf(2 to "Барсик", 1 to "Рыжик", 3 to "Мурзик")
personsSortedMap.put(7, "Васька")
personsSortedMap.remove(3)