Question
How can you iterate over a HashMap in Kotlin?
For example, given a Kotlin map type such as:
typealias HashMap<K, V> = java.util.HashMap<K, V>
what are the common and idiomatic ways to loop through its entries, keys, or values?
Short Answer
By the end of this page, you will understand how to iterate over a HashMap in Kotlin using idiomatic approaches such as looping through entries, keys, and values. You will also see when to use destructuring, forEach, and other common patterns used in real Kotlin codebases.
Concept
In Kotlin, a HashMap is a key-value collection. Each item in the map has:
- a key used to identify the item
- a value stored under that key
When people say they want to “iterate over a HashMap,” they usually mean one of these:
- loop through every key-value pair
- loop through only the keys
- loop through only the values
Although HashMap comes from Java, Kotlin provides cleaner and more readable ways to work with it.
A map matters in real programming because it is often used for:
- configuration settings
- user data by ID
- counting occurrences
- caching values
- request parameters
- lookup tables
In Kotlin, the most common way to iterate a map is to loop through its entries or use destructuring directly in a for loop. This is preferred because it is readable and gives direct access to both the key and the value.
Mental Model
Think of a HashMap like a locker room:
- each key is a locker number
- each value is what is stored inside that locker
Iterating over the map means walking past all the lockers and checking:
- the locker numbers only (
keys) - the contents only (
values) - or both the number and the contents (
entries)
Kotlin makes this easy by letting you open each locker and directly name the two parts:
for ((key, value) in map) {
println("$key -> $value")
}
That syntax is called destructuring: Kotlin splits each map entry into two variables for you.
Syntax and Examples
Basic syntax
Iterate over key-value pairs
val scores = hashMapOf(
"Alice" to 95,
"Bob" to 87,
"Charlie" to 91
)
for ((name, score) in scores) {
println("$name scored $score")
}
This is the most idiomatic Kotlin approach. Each map entry is unpacked into name and score.
Iterate using entries
for (entry in scores.entries) {
println("${entry.key} scored ${entry.value}")
}
Use this when you want the full entry object.
Iterate over keys only
for (name in scores.keys) {
println(name)
}
Iterate over values only
for (score in scores.values) {
println(score)
}
Iterate with forEach
scores.forEach { (name, score) ->
println("$name scored $score")
}
This is also common in Kotlin, especially in functional-style code.
Another beginner-friendly example
val ages = HashMap<String, Int>()
ages["Maya"] = 24
ages["Noah"] = 29
ages["Liam"] = 31
for ((person, age) in ages) {
println("$person is $age years old")
}
This loops through every entry and prints both parts clearly.
Step by Step Execution
Consider this example:
val items = hashMapOf(
"pen" to 2,
"notebook" to 5
)
for ((name, quantity) in items) {
println("$name: $quantity")
}
Here is what happens step by step:
-
A
HashMapnameditemsis created.- key
"pen"has value2 - key
"notebook"has value5
- key
-
The
forloop starts:
for ((name, quantity) in items)
-
Kotlin takes the first entry from the map.
namebecomes the keyquantitybecomes the value
-
The
printlnline runs:
println("$name: $quantity")
- Kotlin moves to the next entry and repeats the same process.
Possible output:
pen: 2
notebook: 5
Note: HashMap does not guarantee insertion order, so in some cases the printed order may differ. If order matters, use linkedMapOf() or another ordered map type.
Real World Use Cases
Iterating over maps is common in many real applications.
Configuration settings
val config = mapOf(
"host" to "localhost",
"port" to "8080",
"mode" to "debug"
)
for ((key, value) in config) {
println("$key = $value")
}
Used for printing or validating settings.
Counting values
val wordCounts = hashMapOf(
"kotlin" to 3,
"java" to 2,
"api" to 5
)
for ((word, count) in wordCounts) {
println("$word appears $count times")
}
Used in text processing and analytics.
API query parameters
val params = mapOf(
"page" to "1",
"sort" to "name"
)
for ((key, value) in params) {
println("$key=$value")
}
Used when building URLs or request payloads.
User lookup data
val users = hashMapOf(
101 to "Ava",
102 to "Ethan"
)
for ((id, name) in users) {
println("User $id is $name")
}
Used in caching, indexing, and data lookup.
Real Codebase Usage
In real Kotlin projects, developers usually choose the iteration style based on what they need.
Common patterns
1. Destructuring for readability
for ((key, value) in settings) {
println("$key -> $value")
}
Best when both parts are needed.
2. Guard clauses while iterating
for ((key, value) in settings) {
if (value.isBlank()) continue
println("Valid setting: $key = $value")
}
Useful for skipping invalid entries early.
3. Validation
for ((field, value) in formData) {
if (value.isBlank()) {
println("$field is required")
}
}
Common in forms, API inputs, and configuration loading.
4. Transformation with collection functions
val uppercased = scores.map { (name, score) ->
"$name: ${score + 1}"
}
In many codebases, developers use map, filter, and forEach instead of a plain loop when transforming data.
5. Error reporting
val errors = mutableMapOf<String, String>()
for ((field, message) in errors) {
println("Error in $field: $message")
}
Maps are often used to store field names and associated messages.
Idiomatic advice
- Use
for ((k, v) in map)when you need both key and value. - Use
map.keysormap.valuesonly when you need one side. - Use
forEachfor short operations. - Prefer Kotlin collection functions when transforming data instead of printing or mutating inside loops.
Common Mistakes
1. Iterating over keys when you need both key and value
Broken or inefficient approach:
for (key in scores.keys) {
println("$key -> ${scores[key]}")
}
This works, but it performs a lookup for each key. A clearer approach is:
for ((key, value) in scores) {
println("$key -> $value")
}
2. Assuming HashMap keeps insertion order
Broken assumption:
val map = hashMapOf("a" to 1, "b" to 2, "c" to 3)
for ((k, v) in map) {
println(k)
}
Do not rely on the output order. If order matters, use an ordered map.
3. Forgetting that keys may not exist
val age = scores["Unknown"]
println(age)
This may print null. Kotlin maps often return nullable values when a key is missing.
Safer approach:
val age = scores["Unknown"] ?: 0
println(age)
4. Confusing Map and MutableMap
val data: Map<String, Int> = mapOf("a" to 1)
// data["b"] = 2 // Error
If you need to add or change entries, use MutableMap or HashMap.
5. Writing overly Java-like Kotlin
Less idiomatic:
val iterator = scores.entries.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
println(entry.key)
}
More idiomatic Kotlin:
for ((key, value) in scores) {
println("$key -> $value")
}
Prefer Kotlin-style loops unless you specifically need an iterator.
Comparisons
| Approach | Example | Best when | Notes |
|---|---|---|---|
| Iterate over map directly | for ((k, v) in map) | You need both key and value | Most idiomatic Kotlin |
Iterate over entries | for (entry in map.entries) | You want the entry object | Slightly more verbose |
Iterate over keys | for (k in map.keys) | You only need keys | Avoid extra lookups if value is also needed |
Iterate over values | for (v in map.values) | You only need values | Clean and simple |
Use forEach | map.forEach { (k, v) -> ... } | Short actions or functional style | Common in Kotlin code |
HashMap vs ordered maps
| Map type | Keeps order? | Use when |
|---|---|---|
HashMap | No | Fast key-value lookup, order does not matter |
LinkedHashMap | Yes, insertion order | You want predictable iteration order |
SortedMap / TreeMap | Sorted by key | You need keys in sorted order |
for loop vs forEach
| Style | Example | Advantage | Trade-off |
|---|---|---|---|
for loop | for ((k, v) in map) | Very readable | Slightly more boilerplate |
forEach | map.forEach { (k, v) -> ... } | Concise | Can be less clear for beginners |
Cheat Sheet
val map = hashMapOf(
"a" to 1,
"b" to 2
)
Iterate over key-value pairs
for ((key, value) in map) {
println("$key -> $value")
}
Iterate with entries
for (entry in map.entries) {
println(entry.key)
println(entry.value)
}
Iterate over keys
for (key in map.keys) {
println(key)
}
Iterate over values
for (value in map.values) {
println(value)
}
Use forEach
map.forEach { (key, value) ->
println("$key -> $value")
}
Key rules
for ((k, v) in map)is the most idiomatic option.HashMapdoes not guarantee iteration order.- Use
LinkedHashMapif order matters. - Accessing
map[key]may returnnull. - Use
keysorvaluesonly when you need one side. - Prefer
MutableMaporHashMapif you need to modify the map.
FAQ
How do I loop through a HashMap in Kotlin?
Use a for loop with destructuring:
for ((key, value) in map) {
println("$key -> $value")
}
What is the most idiomatic way to iterate over a map in Kotlin?
The most idiomatic approach is usually:
for ((key, value) in map)
It is concise and readable.
Can I iterate over only the keys or only the values?
Yes.
for (key in map.keys) { }
for (value in map.values) { }
Does HashMap preserve insertion order in Kotlin?
No. If you need predictable iteration order, use LinkedHashMap or linkedMapOf().
What does (key, value) mean in a Kotlin for loop?
It is destructuring. Kotlin takes each map entry and splits it into separate key and value variables.
Should I use forEach or a for loop for maps in Kotlin?
Both are valid. Use a for loop for clarity, especially as a beginner. Use forEach when you prefer a shorter functional style.
Can I modify a HashMap while iterating over it?
Be careful. Modifying a collection while iterating can cause problems. If you need to update it, consider collecting changes first or using safe mutation patterns.
Mini Project
Description
Build a small inventory viewer in Kotlin that stores product names and quantities in a HashMap and prints the data in different ways. This demonstrates how to iterate over entries, keys, and values in a practical program.
Goal
Create a Kotlin program that reads a map of inventory items and displays full entries, product names only, and quantities only.
Requirements
- Create a
HashMapwith at least three inventory items - Print every item as
name -> quantity - Print all product names separately
- Print all quantities separately
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.