Watch the video (12 min)
On this page26 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Three Views of a Map
  5. 2. Looping Over Keys or Values
  6. 3. Looping Over Entries
  7. 4. forEach — A Function for Every Pair
  8. 5. update and ifAbsent
  9. 6. updateAll — Change Every Value
  10. 7. removeWhere — Delete Matching Entries
  11. 8. Don't Change a Map While Looping Over It
  12. 9. map() — Transform Into a New Map
  13. 10. Building a Map With Collection for
  14. 11. Counting Occurrences
  15. 12. Grouping Values Into Lists
  16. 13. Sorting Entries for Display
  17. 14. A Real-World Example
  18. Code Examples
  19. Common Beginner Mistakes
  20. Best Practices
  21. Mini Challenge
  22. Practice Questions
  23. Practice Answers
  24. Quick Revision
  25. Key Takeaways
  26. What's Next?

Lecture 50 — Map Iteration & Methods

Category8 — Sets & Maps
Lecture050 of 140
Estimated video length12 min
TargetDart 3.12.2
LevelBeginner

So far we used a map one key at a time. Looping over its entries and using methods like update and removeWhere lets 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-in loops (Lecture 027) and the ?? operator (Lecture 014)
  • arrow and anonymous functions (Lecture 034)
  • map, where, toList (Lecture 043) and sorting with compareTo (Lecture 045)
  • collection for and if (Lecture 046)
  • map literals, map[key] returning a nullable value, adding, updating and removing keys, containsKey, and putIfAbsent (Lecture 049)

Connection With Previous Lectures

In Lecture 049 we always knew which key we wanted:

dart
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, and entries
  • Loop over a map's entries with for-in, using entry.key and entry.value
  • Visit every pair with forEach((key, value) => …)
  • Change values with update, ifAbsent, and updateAll, and delete with removeWhere
  • Build a new map with map() and with collection for
  • 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".

dart
void main() {
  var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
  print(prices.keys);
  print(prices.values);
  print(prices.entries);
}
output
(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.

dart
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');
}
output
Items: [Milk, Bread, Eggs]
Total: 670

toList() 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.

dart
void main() {
  var marks = {'Ali': 72, 'Sara': 95, 'Zayan': 88};
  for (final entry in marks.entries) {
    print('${entry.key} scored ${entry.value}');
  }
}
output
Ali scored 72
Sara scored 95
Zayan scored 88

You 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.

dart
void main() {
  var stock = {'Pen': 40, 'Notebook': 12, 'Bag': 3};
  stock.forEach((item, count) => print('$item: $count left'));
}
output
Pen: 40 left
Notebook: 12 left
Bag: 3 left

It 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.

dart
void main() {
  var balances = {'Ali': 1000, 'Sara': 500};
  balances.update('Ali', (balance) => balance + 250);
  balances.update('Zayan', (balance) => balance + 100, ifAbsent: () => 100);
  print(balances);
}
output
{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.

dart
void main() {
  var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
  prices.updateAll((item, price) => price + 10);
  print(prices);
}
output
{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.

dart
void main() {
  var stock = {'Pen': 40, 'Notebook': 0, 'Bag': 3, 'Ruler': 0};
  stock.removeWhere((item, count) => count == 0);
  print(stock);
}
output
{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:

dart
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
    }
  }
}
output
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).

dart
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);
}
output
{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.

dart
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);
}
output
{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.

dart
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);
}
output
{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.

dart
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);
}
output
{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).

dart
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}');
  }
}
output
Sara: 95
Zayan: 88
Ali: 72

b 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

dart
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');
}
output
milk: 2 sold, 500 earned
tea: 3 sold, 450 earned
bread: 1 sold, 120 earned
Total: 1070

One 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

dart
void main() {
  var capitals = {'Pakistan': 'Islamabad', 'Japan': 'Tokyo'};
  print(capitals.keys.toList());
  print(capitals.values.toList());
  print(capitals.length);
}
output
[Pakistan, Japan]
[Islamabad, Tokyo]
2

Example 2 — Printing Every Entry

dart
void main() {
  var ages = {'Ali': 20, 'Sara': 18, 'Zayan': 6};
  for (final entry in ages.entries) {
    print('${entry.key} is ${entry.value}');
  }
}
output
Ali is 20
Sara is 18
Zayan is 6

Example 3 — forEach With Two Parameters

dart
void main() {
  var colors = {'red': '#FF0000', 'green': '#00FF00'};
  colors.forEach((name, code) => print('$name = $code'));
}
output
red = #FF0000
green = #00FF00

Example 4 — Doubling Every Value

dart
void main() {
  var points = {'Ali': 5, 'Sara': 8};
  points.updateAll((name, value) => value * 2);
  print(points);
}
output
{Ali: 10, Sara: 16}

Example 5 — Swapping Keys and Values

dart
void main() {
  var codes = {'PK': 'Pakistan', 'JP': 'Japan'};
  var reversed = codes.map((code, country) => MapEntry(country, code));
  print(reversed);
}
output
{Pakistan: PK, Japan: JP}

Example 6 — Counting Letters

dart
void main() {
  var counts = <String, int>{};
  for (final letter in 'banana'.split('')) {
    counts[letter] = (counts[letter] ?? 0) + 1;
  }
  print(counts);
}
output
{b: 1, a: 3, n: 2}

Example 7 — Student Marks: Class Report

dart
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}');
}
output
Ali: 72 (pass)
Sara: 95 (pass)
Zayan: 48 (fail)
Hina: 81 (pass)
Average: 74.0

How it works

  1. Each entry gives a name and a mark together, so one loop prints and totals.
  2. total / marks.length uses /, so the average is a double.

Example 8 — Shopping Total With a Discount

dart
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');
}
output
{Milk: 200, Tea: 550}
Total: 750

How it works

  1. updateAll takes 50 off every price above 200.
  2. removeWhere drops 'Bread'; the loop then only reads the values.

Example 9 — Bank Balance: Applying Transactions

dart
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);
}
output
{Ali: 1050, Sara: 700, Zayan: 300}

How it works

  1. We loop over deposits and change balances — two different maps, so this is safe.
  2. ifAbsent opens a new account for 'Zayan' with his first deposit.

Example 10 — Temperature: Grouping Days

dart
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);
}
output
{warm: [Mon, Wed, Thu], cool: [Tue, Fri]}

How it works

  1. The label ('warm' or 'cool') is the group key; the day is added to that group's list.
  2. putIfAbsent creates each list the first time its label appears.

Common Beginner Mistakes

1. update on a missing key without ifAbsent

dart
void main() {
  var counts = {'tea': 1};
  counts.update('milk', (n) => n + 1); // ✗ no 'milk' key
}
output
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()

dart
void main() {
  var prices = {'Milk': 250};
  var doubled = prices.map((item, price) => price * 2); // ✗
}
output
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

dart
void main() {
  var marks = {'Ali': 72};
  marks.forEach((name) => print(name)); // ✗ needs key and value
}
output
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

dart
void main() {
  var marks = {'Ali': 72};
  print(marks.keys[0]); // ✗ an iterable has no index
}
output
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

dart
void main() {
  var marks = {'Ali': 72, 'Sara': 95};
  marks.sort(); // ✗ maps have no sort
}
output
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?:

output
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 entries when you need both key and value.
  • Use forEach for short one-line actions; use for-in for longer bodies.
  • Count with update(…, ifAbsent: …) or (map[key] ?? 0) + 1.
  • Group with putIfAbsent(key, () => []).add(value).
  • Use removeWhere and updateAll instead of changing a map inside a loop.
  • Use map() or collection for when 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.

output
Ali: 3
Sara: 2
Zayan: 1

Try it yourself before opening the solution.

Show solution
dart
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}');
  }
}
output
Ali: 3
Sara: 2
Zayan: 1

Practice Questions

Work through these in order — they run from beginner to application to challenge.

Beginner

  1. Given {'a': 1, 'b': 2, 'c': 3}, print its keys as a list and its values as a list.
  2. Given {'Ali': 20, 'Sara': 18}, print each entry as Ali -> 20 using a for-in over entries.
  3. Given {'Pen': 40, 'Bag': 3}, print each pair as Pen: 40 using forEach.

Application

  1. Given {'Milk': 250, 'Bread': 120, 'Eggs': 300}, print the sum of all values.
  2. Given {'Ali': 72, 'Sara': 95}, add 5 to every mark with updateAll and print the map.
  3. Given {'Pen': 40, 'Notebook': 0, 'Bag': 3}, remove every entry with a count below 5 and print the map.
  4. Given the list ['red', 'blue', 'red', 'green', 'red'], count each color and print the map.
  5. Given {'Ali': 72, 'Sara': 95, 'Zayan': 48}, use collection for to build a map of only the marks below 80, and print it.

Challenge

  1. Given ['apple', 'avocado', 'banana', 'blueberry', 'cherry'], group the words by their first letter into a Map<String, List<String>> and print it.
  2. Given {'Lahore': 31, 'Murree': 14, 'Karachi': 34}, print the cities from coolest to warmest as Murree: 14, one per line.

Practice Answers

Question 1 — Solution

dart
void main() {
  var letters = {'a': 1, 'b': 2, 'c': 3};
  print(letters.keys.toList());
  print(letters.values.toList());
}
output
[a, b, c]
[1, 2, 3]

Question 2 — Solution

dart
void main() {
  var ages = {'Ali': 20, 'Sara': 18};
  for (final entry in ages.entries) {
    print('${entry.key} -> ${entry.value}');
  }
}
output
Ali -> 20
Sara -> 18

Question 3 — Solution

dart
void main() {
  var stock = {'Pen': 40, 'Bag': 3};
  stock.forEach((item, count) => print('$item: $count'));
}
output
Pen: 40
Bag: 3

Question 4 — Solution

dart
void main() {
  var prices = {'Milk': 250, 'Bread': 120, 'Eggs': 300};
  var total = 0;
  for (final price in prices.values) {
    total += price;
  }
  print(total);
}
output
670

Question 5 — Solution

dart
void main() {
  var marks = {'Ali': 72, 'Sara': 95};
  marks.updateAll((name, mark) => mark + 5);
  print(marks);
}
output
{Ali: 77, Sara: 100}

Question 6 — Solution

dart
void main() {
  var stock = {'Pen': 40, 'Notebook': 0, 'Bag': 3};
  stock.removeWhere((item, count) => count < 5);
  print(stock);
}
output
{Pen: 40}

Question 7 — Solution

dart
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);
}
output
{red: 3, blue: 1, green: 1}

Question 8 — Solution

dart
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);
}
output
{Ali: 72, Zayan: 48}

Question 9 — Solution

dart
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);
}
output
{a: [apple, avocado], b: [banana, blueberry], c: [cherry]}

Question 10 — Solution

dart
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}');
  }
}
output
Murree: 14
Lahore: 31
Karachi: 34

a before b sorts from lowest to highest.


Quick Revision

  1. What are a map's three views?
  2. What two properties does a MapEntry have?
  3. How many parameters does the function passed to a map's forEach take?
  4. What happens when update meets a missing key without ifAbsent?
  5. What is the difference between updateAll and map()?
  6. What must the function passed to map() return?
  7. How do you group values with putIfAbsent?
  8. Why can't you call sort on a map, and what do you do instead?

Key Takeaways

  • keys, values, and entries are iterables; toList() turns them into lists.
  • Loop over entries to get each MapEntry's key and value — the value is not nullable.
  • A map's forEach takes a function of two parameters: key and value.
  • update changes one value from its old value; ifAbsent handles a missing key.
  • updateAll changes every value in place; removeWhere deletes every matching entry.
  • map() builds a new map from MapEntry results; collection for builds one too.
  • Count with update(…, ifAbsent: …); group with putIfAbsent(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.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.