On this page26 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. Three Views of a Map
- 2. Looping Over Keys or Values
- 3. Looping Over Entries
- 4. forEach — A Function for Every Pair
- 5. update and ifAbsent
- 6. updateAll — Change Every Value
- 7. removeWhere — Delete Matching Entries
- 8. Don't Change a Map While Looping Over It
- 9. map() — Transform Into a New Map
- 10. Building a Map With Collection for
- 11. Counting Occurrences
- 12. Grouping Values Into Lists
- 13. Sorting Entries for Display
- 14. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 50 — Map Iteration & Methods
| Category | 8 — Sets & Maps |
| Lecture | 050 of 140 |
| Estimated video length | 12 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
So far we used a map one key at a time. Looping over its entries and using methods like
updateandremoveWherelets us count, group, and report on a whole map at once.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.
Prerequisites
Students should already understand, from Lectures 001–049:
for-inloops (Lecture 027) and the??operator (Lecture 014)- arrow and anonymous functions (Lecture 034)
map,where,toList(Lecture 043) and sorting withcompareTo(Lecture 045)- collection
forandif(Lecture 046) - map literals,
map[key]returning a nullable value, adding, updating and removing keys,containsKey, andputIfAbsent(Lecture 049)
Connection With Previous Lectures
In Lecture 049 we always knew which key we wanted:
print(prices['Milk']);But real questions are about the whole map. What is the total of every price? Which student scored highest? How many times does each word appear in a sentence? We cannot answer those by typing keys one by one — we may not even know what the keys are. We need ways to walk through a map and to change many entries at once.
Learning Objectives
By the end of this lecture you will be able to:
- Read a map's
keys,values, andentries - Loop over a map's entries with
for-in, usingentry.keyandentry.value - Visit every pair with
forEach((key, value) => …) - Change values with
update,ifAbsent, andupdateAll, and delete withremoveWhere - Build a new map with
map()and with collectionfor - Count occurrences and group values into a
Map<String, List<…>> - Sort a map's entries for display
- Avoid changing a map while looping over it
1. Three Views of a Map
A map gives you three ways to look at its contents: just the keys, just the values, or the key–value pairs together, called entries.
Analogy — think of a price board in a shop. You can read only the item names down the left, only the prices down the right, or each row as a whole: "Milk — 250".
void main() {
var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
print(prices.keys);
print(prices.values);
print(prices.entries);
}(Milk, Bread, Eggs)
(250, 120, 300)
(MapEntry(Milk: 250), MapEntry(Bread: 120), MapEntry(Eggs: 300))The round brackets show these are iterables (Lecture 046), not lists. A map literal keeps its keys in the order you added them, so loops visit them in that order too.
2. Looping Over Keys or Values
keys and values work in a for-in loop just like a list.
void main() {
var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
var total = 0;
for (final price in prices.values) {
total += price;
}
print('Items: ${prices.keys.toList()}');
print('Total: $total');
}Items: [Milk, Bread, Eggs]
Total: 670toList() turns the keys into a real list when you need one — for example to use an index.
3. Looping Over Entries
When you need the key and the value, loop over entries. Each element is a MapEntry
with two properties: key and value.
void main() {
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 88};
for (final entry in marks.entries) {
print('${entry.key} scored ${entry.value}');
}
}Ali scored 72
Sara scored 95
Zayan scored 88You could loop over keys and write marks[name], but that value is nullable (int?), as
Lecture 049 showed. entry.value is a plain int — no ! and no ?? needed.
Dart can also unpack an entry straight into two variables in the loop header. That uses patterns, which we study in Category 13 — Patterns & Modern Dart.
4. forEach — A Function for Every Pair
A map's forEach takes a function with two parameters: the key and the value.
void main() {
var stock = {'Pen': 40, 'Notebook': 12, 'Bag': 3};
stock.forEach((item, count) => print('$item: $count left'));
}Pen: 40 left
Notebook: 12 left
Bag: 3 leftIt is handy for a one-line action. For anything longer, or when you need break, a for-in
over entries is clearer.
5. update and ifAbsent
update(key, function) replaces a value using the old one. The function receives the current
value and returns the new one.
void main() {
var balances = {'Ali': 1000, 'Sara': 500};
balances.update('Ali', (balance) => balance + 250);
balances.update('Zayan', (balance) => balance + 100, ifAbsent: () => 100);
print(balances);
}{Ali: 1250, Sara: 500, Zayan: 100}'Zayan' was not in the map, so the named argument ifAbsent supplied his starting value.
Without ifAbsent, a missing key stops the program (see
Common Mistakes).
6. updateAll — Change Every Value
updateAll calls your function once per entry with the key and value, and stores what it
returns.
void main() {
var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
prices.updateAll((item, price) => price + 10);
print(prices);
}{Milk: 260, Bread: 130, Eggs: 310}The keys stay the same; only the values change. The new values must still be int.
7. removeWhere — Delete Matching Entries
Like the list version from Lecture 041, but the function receives the key and the value.
void main() {
var stock = {'Pen': 40, 'Notebook': 0, 'Bag': 3, 'Ruler': 0};
stock.removeWhere((item, count) => count == 0);
print(stock);
}{Pen: 40, Bag: 3}8. Don't Change a Map While Looping Over It
Adding or removing keys inside a loop over the same map stops the program, exactly as with lists:
void main() {
var stock = {'Pen': 40, 'Notebook': 0, 'Bag': 3};
for (final item in stock.keys) {
if (stock[item] == 0) {
stock.remove(item); // ✗ changes the map mid-loop
}
}
}Unhandled exception:
Concurrent modification during iteration: _Map len:2.Use removeWhere for removing, and updateAll for changing every value.
9. map() — Transform Into a New Map
A map's map() method builds a new map. Your function receives each key and value and must
return a MapEntry(newKey, newValue).
void main() {
var celsius = {'Lahore': 31.0, 'Murree': 14.0};
var fahrenheit = celsius.map(
(city, temp) => MapEntry(city.toUpperCase(), temp * 9 / 5 + 32),
);
print(fahrenheit);
print(celsius);
}{LAHORE: 87.8, MURREE: 57.2}
{Lahore: 31.0, Murree: 14.0}Unlike updateAll, map() can change the keys too, and the original map is untouched.
10. Building a Map With Collection for
The collection for and if from Lecture 046 work inside map braces: each pass of the loop
writes one key: value pair.
void main() {
var names = ['Ali', 'Sara', 'Zayan'];
var lengths = {for (final name in names) name: name.length};
print(lengths);
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 48};
var passed = {
for (final entry in marks.entries)
if (entry.value >= 50) entry.key: entry.value,
};
print(passed);
}{Ali: 3, Sara: 4, Zayan: 5}
{Ali: 72, Sara: 95}The second map is a filtered copy — a pattern you will use constantly.
11. Counting Occurrences
Counting is the classic job for a map: the key is the thing, the value is how many times it
appeared. update with ifAbsent does it in one line.
void main() {
var text = 'the cat and the dog and the bird';
var counts = <String, int>{};
for (final word in text.split(' ')) {
counts.update(word, (count) => count + 1, ifAbsent: () => 1);
}
print(counts);
}{the: 3, cat: 1, and: 2, dog: 1, bird: 1}An equally common spelling uses ?? from Lecture 014: counts[word] = (counts[word] ?? 0) + 1;
— "the old count, or zero, plus one".
12. Grouping Values Into Lists
To group, the value is a list: Map<String, List<String>>. putIfAbsent returns the value
stored under the key — the existing list, or the new empty one it just added — so you can
add to it immediately.
void main() {
var students = ['Ali', 'Sara', 'Zayan', 'Sana', 'Asad'];
var byLetter = <String, List<String>>{};
for (final name in students) {
byLetter.putIfAbsent(name[0], () => []).add(name);
}
print(byLetter);
}{A: [Ali, Asad], S: [Sara, Sana], Z: [Zayan]}13. Sorting Entries for Display
A map has no sort method. To show it in order, copy the entries into a list and sort the
list with compareTo (Lecture 045).
void main() {
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 88};
var ranked = marks.entries.toList();
ranked.sort((a, b) => b.value.compareTo(a.value));
for (final entry in ranked) {
print('${entry.key}: ${entry.value}');
}
}Sara: 95
Zayan: 88
Ali: 72b before a sorts from highest to lowest. Use a.key.compareTo(b.key) to sort by name. If
you need a sorted map afterwards, Map.fromEntries(ranked) builds one in that order.
14. A Real-World Example
void main() {
var sales = ['tea', 'milk', 'tea', 'bread', 'tea', 'milk'];
var prices = {'tea': 150, 'milk': 250, 'bread': 120};
var counts = <String, int>{};
for (final item in sales) {
counts.update(item, (n) => n + 1, ifAbsent: () => 1);
}
var income = counts.map((item, n) => MapEntry(item, n * (prices[item] ?? 0)));
var ranked = income.entries.toList();
ranked.sort((a, b) => b.value.compareTo(a.value));
var total = 0;
income.forEach((item, amount) => total += amount);
for (final entry in ranked) {
print('${entry.key}: ${counts[entry.key]} sold, ${entry.value} earned');
}
print('Total: $total');
}milk: 2 sold, 500 earned
tea: 3 sold, 450 earned
bread: 1 sold, 120 earned
Total: 1070One list of sales becomes a count map, then an income map, then a sorted report — counting, transforming, iterating, and sorting together.
Code Examples
Example 1 — Keys and Values as Lists
void main() {
var capitals = {'Pakistan': 'Islamabad', 'Japan': 'Tokyo'};
print(capitals.keys.toList());
print(capitals.values.toList());
print(capitals.length);
}[Pakistan, Japan]
[Islamabad, Tokyo]
2Example 2 — Printing Every Entry
void main() {
var ages = {'Ali': 20, 'Sara': 18, 'Zayan': 6};
for (final entry in ages.entries) {
print('${entry.key} is ${entry.value}');
}
}Ali is 20
Sara is 18
Zayan is 6Example 3 — forEach With Two Parameters
void main() {
var colors = {'red': '#FF0000', 'green': '#00FF00'};
colors.forEach((name, code) => print('$name = $code'));
}red = #FF0000
green = #00FF00Example 4 — Doubling Every Value
void main() {
var points = {'Ali': 5, 'Sara': 8};
points.updateAll((name, value) => value * 2);
print(points);
}{Ali: 10, Sara: 16}Example 5 — Swapping Keys and Values
void main() {
var codes = {'PK': 'Pakistan', 'JP': 'Japan'};
var reversed = codes.map((code, country) => MapEntry(country, code));
print(reversed);
}{Pakistan: PK, Japan: JP}Example 6 — Counting Letters
void main() {
var counts = <String, int>{};
for (final letter in 'banana'.split('')) {
counts[letter] = (counts[letter] ?? 0) + 1;
}
print(counts);
}{b: 1, a: 3, n: 2}Example 7 — Student Marks: Class Report
void main() {
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 48, 'Hina': 81};
var total = 0;
for (final entry in marks.entries) {
var result = entry.value >= 50 ? 'pass' : 'fail';
print('${entry.key}: ${entry.value} ($result)');
total += entry.value;
}
print('Average: ${total / marks.length}');
}Ali: 72 (pass)
Sara: 95 (pass)
Zayan: 48 (fail)
Hina: 81 (pass)
Average: 74.0How it works
- Each entry gives a name and a mark together, so one loop prints and totals.
total / marks.lengthuses/, so the average is adouble.
Example 8 — Shopping Total With a Discount
void main() {
var cart = {'Milk': 250, 'Bread': 120, 'Tea': 600};
cart.updateAll((item, price) => price > 200 ? price - 50 : price);
cart.removeWhere((item, price) => item == 'Bread');
var total = 0;
for (final price in cart.values) {
total += price;
}
print(cart);
print('Total: $total');
}{Milk: 200, Tea: 550}
Total: 750How it works
updateAlltakes 50 off every price above 200.removeWheredrops'Bread'; the loop then only reads the values.
Example 9 — Bank Balance: Applying Transactions
void main() {
var balances = {'Ali': 1000, 'Sara': 500};
var deposits = {'Sara': 200, 'Zayan': 300, 'Ali': 50};
deposits.forEach((name, amount) {
balances.update(name, (old) => old + amount, ifAbsent: () => amount);
});
print(balances);
}{Ali: 1050, Sara: 700, Zayan: 300}How it works
- We loop over
depositsand changebalances— two different maps, so this is safe. ifAbsentopens a new account for'Zayan'with his first deposit.
Example 10 — Temperature: Grouping Days
void main() {
var temps = {'Mon': 31, 'Tue': 18, 'Wed': 26, 'Thu': 33, 'Fri': 15};
var groups = <String, List<String>>{};
for (final entry in temps.entries) {
var label = entry.value >= 25 ? 'warm' : 'cool';
groups.putIfAbsent(label, () => []).add(entry.key);
}
print(groups);
}{warm: [Mon, Wed, Thu], cool: [Tue, Fri]}How it works
- The label (
'warm'or'cool') is the group key; the day is added to that group's list. putIfAbsentcreates each list the first time its label appears.
Common Beginner Mistakes
1. update on a missing key without ifAbsent
void main() {
var counts = {'tea': 1};
counts.update('milk', (n) => n + 1); // ✗ no 'milk' key
}Unhandled exception:
Invalid argument (key): Key not in map.: "milk"Add ifAbsent: () => 1 whenever the key might be new.
2. Adding or removing keys while looping
Changing the size of a map inside a for-in over it throws
Concurrent modification during iteration (see
section 8). Use removeWhere.
3. Returning a plain value from map()
void main() {
var prices = {'Milk': 250};
var doubled = prices.map((item, price) => price * 2); // ✗
}Error: A value of type 'int' can't be returned from a function with return type 'MapEntry<dynamic, dynamic>'.Return MapEntry(item, price * 2) — or use updateAll to change values in place.
4. Giving forEach only one parameter
void main() {
var marks = {'Ali': 72};
marks.forEach((name) => print(name)); // ✗ needs key and value
}Error: The argument type 'void Function(String)' can't be assigned to the parameter type 'void Function(String, int)'.5. Indexing keys like a list
void main() {
var marks = {'Ali': 72};
print(marks.keys[0]); // ✗ an iterable has no index
}Error: The operator '[]' isn't defined for the type 'Iterable<String>'.Use marks.keys.first, or marks.keys.toList()[0].
6. Trying to sort a map
void main() {
var marks = {'Ali': 72, 'Sara': 95};
marks.sort(); // ✗ maps have no sort
}Error: The method 'sort' isn't defined for the type 'Map<String, int>'.Sort marks.entries.toList() instead.
7. Using map[key] where entry.value would do
total += marks[name]; inside a loop over keys fails because marks[name] is int?:
Error: A value of type 'int?' can't be assigned to a variable of type 'num'.Loop over entries and use entry.value, which is never null.
Best Practices
- Loop over
entrieswhen you need both key and value. - Use
forEachfor short one-line actions; usefor-infor longer bodies. - Count with
update(…, ifAbsent: …)or(map[key] ?? 0) + 1. - Group with
putIfAbsent(key, () => []).add(value). - Use
removeWhereandupdateAllinstead of changing a map inside a loop. - Use
map()or collectionforwhen you want a new map and the original kept. - Sort a list of entries for display; the map itself stays in insertion order.
Mini Challenge
Count the votes ['Ali', 'Sara', 'Ali', 'Zayan', 'Sara', 'Ali'], then print the results from
most to fewest votes.
Ali: 3
Sara: 2
Zayan: 1Try it yourself before opening the solution.
Show solution
void main() {
var votes = ['Ali', 'Sara', 'Ali', 'Zayan', 'Sara', 'Ali'];
var counts = <String, int>{};
for (final name in votes) {
counts.update(name, (n) => n + 1, ifAbsent: () => 1);
}
var ranked = counts.entries.toList();
ranked.sort((a, b) => b.value.compareTo(a.value));
for (final entry in ranked) {
print('${entry.key}: ${entry.value}');
}
}Ali: 3
Sara: 2
Zayan: 1Practice Questions
Work through these in order — they run from beginner to application to challenge.
Beginner
- Given
{'a': 1, 'b': 2, 'c': 3}, print its keys as a list and its values as a list. - Given
{'Ali': 20, 'Sara': 18}, print each entry asAli -> 20using afor-inoverentries. - Given
{'Pen': 40, 'Bag': 3}, print each pair asPen: 40usingforEach.
Application
- Given
{'Milk': 250, 'Bread': 120, 'Eggs': 300}, print the sum of all values. - Given
{'Ali': 72, 'Sara': 95}, add5to every mark withupdateAlland print the map. - Given
{'Pen': 40, 'Notebook': 0, 'Bag': 3}, remove every entry with a count below5and print the map. - Given the list
['red', 'blue', 'red', 'green', 'red'], count each color and print the map. - Given
{'Ali': 72, 'Sara': 95, 'Zayan': 48}, use collectionforto build a map of only the marks below80, and print it.
Challenge
- Given
['apple', 'avocado', 'banana', 'blueberry', 'cherry'], group the words by their first letter into aMap<String, List<String>>and print it. - Given
{'Lahore': 31, 'Murree': 14, 'Karachi': 34}, print the cities from coolest to warmest asMurree: 14, one per line.
Practice Answers
Question 1 — Solution
void main() {
var letters = {'a': 1, 'b': 2, 'c': 3};
print(letters.keys.toList());
print(letters.values.toList());
}[a, b, c]
[1, 2, 3]Question 2 — Solution
void main() {
var ages = {'Ali': 20, 'Sara': 18};
for (final entry in ages.entries) {
print('${entry.key} -> ${entry.value}');
}
}Ali -> 20
Sara -> 18Question 3 — Solution
void main() {
var stock = {'Pen': 40, 'Bag': 3};
stock.forEach((item, count) => print('$item: $count'));
}Pen: 40
Bag: 3Question 4 — Solution
void main() {
var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
var total = 0;
for (final price in prices.values) {
total += price;
}
print(total);
}670Question 5 — Solution
void main() {
var marks = {'Ali': 72, 'Sara': 95};
marks.updateAll((name, mark) => mark + 5);
print(marks);
}{Ali: 77, Sara: 100}Question 6 — Solution
void main() {
var stock = {'Pen': 40, 'Notebook': 0, 'Bag': 3};
stock.removeWhere((item, count) => count < 5);
print(stock);
}{Pen: 40}Question 7 — Solution
void main() {
var colors = ['red', 'blue', 'red', 'green', 'red'];
var counts = <String, int>{};
for (final color in colors) {
counts.update(color, (n) => n + 1, ifAbsent: () => 1);
}
print(counts);
}{red: 3, blue: 1, green: 1}Question 8 — Solution
void main() {
var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 48};
var below = {
for (final entry in marks.entries)
if (entry.value < 80) entry.key: entry.value,
};
print(below);
}{Ali: 72, Zayan: 48}Question 9 — Solution
void main() {
var words = ['apple', 'avocado', 'banana', 'blueberry', 'cherry'];
var groups = <String, List<String>>{};
for (final word in words) {
groups.putIfAbsent(word[0], () => []).add(word);
}
print(groups);
}{a: [apple, avocado], b: [banana, blueberry], c: [cherry]}Question 10 — Solution
void main() {
var temps = {'Lahore': 31, 'Murree': 14, 'Karachi': 34};
var sorted = temps.entries.toList();
sorted.sort((a, b) => a.value.compareTo(b.value));
for (final entry in sorted) {
print('${entry.key}: ${entry.value}');
}
}Murree: 14
Lahore: 31
Karachi: 34a before b sorts from lowest to highest.
Quick Revision
- What are a map's three views?
- What two properties does a
MapEntryhave? - How many parameters does the function passed to a map's
forEachtake? - What happens when
updatemeets a missing key withoutifAbsent? - What is the difference between
updateAllandmap()? - What must the function passed to
map()return? - How do you group values with
putIfAbsent? - Why can't you call
sorton a map, and what do you do instead?
Key Takeaways
keys,values, andentriesare iterables;toList()turns them into lists.- Loop over
entriesto get eachMapEntry'skeyandvalue— the value is not nullable. - A map's
forEachtakes a function of two parameters: key and value. updatechanges one value from its old value;ifAbsenthandles a missing key.updateAllchanges every value in place;removeWheredeletes every matching entry.map()builds a new map fromMapEntryresults; collectionforbuilds one too.- Count with
update(…, ifAbsent: …); group withputIfAbsent(key, () => []).add(…). - To display a map in order, sort a list of its entries.
- Adding or removing keys while looping over a map throws a concurrent modification error.
What's Next?
Lecture 51 — List vs Set vs Map. You now know all three core collections. Next we compare them side by side — ordering, duplicates, lookup speed — so you can choose the right one for each job.