Как перебрать (итерировать) HashMap в Kotlin? Все способы с примерами
1. Проблема с простым циклом for
В вашем коде ошибка в том, что HashMap сам по себе не реализует интерфейс Iterable для пар "ключ-значение" напрямую. Компилятор ожидает, что вы укажете, как именно вы хотите итерировать: по ключам, по значениям или по парам.
Вот как это исправить самым простым способом — используя деструктуризацию в цикле for:
fun main() {
val users: HashMap<Int, String> = hashMapOf(
1 to "Анна",
2 to "Борис",
3 to "Виктор"
)
// ✅ Правильный способ: перебор по парам (ключ, значение)
for ((id, name) in users) {
println("Пользователь $name имеет ID = $id")
}
}
2. Основные способы итерации
Kotlin предоставляет несколько удобных методов для работы с HashMap. Вот полный список:
- По парам "ключ-значение":
for ((k, v) in map) { ... }— самый частый вариант. - Только по ключам:
for (key in map.keys) { ... } - Только по значениям:
for (value in map.values) { ... } - Через entrySet():
for (entry in map.entries) { ... }— Java-стиль, но тоже работает.
3. Функциональный стиль (рекомендуемый)
В современном Kotlin принято использовать функции высшего порядка для работы с коллекциями. Это делает код более читаемым и лаконичным:
fun main() {
val users = hashMapOf(1 to "Анна", 2 to "Борис", 3 to "Виктор")
// forEach с деструктуризацией
users.forEach { (id, name) ->
println("$id -> $name")
}
// Преобразование ключей
val updatedKeys = users.mapKeys { it.key + 10 }
println(updatedKeys) // {11=Анна, 12=Борис, 13=Виктор}
// Преобразование значений (например, сделать все имена заглавными)
val upperNames = users.mapValues { it.value.uppercase() }
println(upperNames) // {1=АННА, 2=БОРИС, 3=ВИКТОР}
// Фильтрация
val filtered = users.filter { it.key > 1 }
println(filtered) // {2=Борис, 3=Виктор}
// Получить список значений, преобразованных в другой тип
val nameLengths = users.map { (id, name) -> "ID=$id, Длина имени=${name.length}" }
println(nameLengths) // [ID=1, Длина имени=4, ...]
}
4. Важные нюансы
- Изменение во время итерации: Нельзя добавлять или удалять элементы из
HashMapво время итерации черезforEachилиfor. Это вызоветConcurrentModificationException. Если нужно изменить, используйтеmutableMapи итератор:
val mutableUsers = users.toMutableMap()
val iterator = mutableUsers.iterator()
while (iterator.hasNext()) {
val (id, name) = iterator.next()
if (id == 2) iterator.remove() // безопасное удаление
}
- Производительность: Все перечисленные методы (кроме явного
iterator()) имеют сложность O(n), так как проходят по всей карте. Для больших карт (миллионы записей) используйтеasSequence()для ленивых вычислений:
users.asSequence()
.filter { it.key % 2 == 0 }
.map { it.value.uppercase() }
.toList() // только здесь выполняется
5. Итоговая рекомендация
Для 90% случаев используйте forEach с деструктуризацией или цикл for с парой. Если нужно преобразовать карту — применяйте mapKeys и mapValues. Это самый идиоматичный Kotlin-код.
Альтернативный подход: Использование Java-стиля для мигрантов
Если вы только перешли с Java и чувствуете себя неуверенно в функциональном стиле, можете сначала использовать привычные методы, а затем постепенно переходить на Kotlin-идиомы. Вот как выглядит "гибридный" подход:
val map = hashMapOf("a" to 1, "b" to 2, "c" to 3)
// Java-стиль через entrySet()
for (entry in map.entries) {
println("${entry.key} = ${entry.value}")
}
// Только ключи
for (key in map.keys) {
println("Ключ: $key")
}
// Только значения
for (value in map.values) {
println("Значение: $value")
}
Когда это полезно? Если вы пишете код, который будет читать Java-разработчик, или если вам нужно выполнить сложные операции с итератором (например, удаление элементов во время обхода).
Недостаток: Этот код менее лаконичен и не использует всю мощь Kotlin (деструктуризацию, цепочки вызовов). Но как первый шаг — вполне нормально. Со временем вы привыкнете к forEach и map, и будете писать меньше кода с тем же результатом.
Также помните, что HashMap в Kotlin — это просто обёртка над Java-классом java.util.HashMap, поэтому все Java-методы также доступны.
Ответов пока нет.
Войдите чтобы оставить ответ