Maps in Dart
By Syncfusion®, Inc. · Last updated
How to store key-value pairs, read and change values by key, handle missing keys, and add, remove, search, loop over and transform maps.
What Is a Map?
Map = a collection of key-value pairs. You find each value by its key.
Key = the label you look up, like 'Maths'.
Value = what the key gives you, like 92.
For example:
- subject → marks:
'Maths'→92 - roll number → name:
21→'Asha' - English word → Hindi word:
'water'→'paani'
Simple lesson: a map links each key to one value, so you can find a value by its name instead of its position.
A Real-World Example
Think of a dictionary.
- You do not read it from page 1 to find "elephant".
- You look up the word (the key), and read its meaning (the value).
- Every word appears once. A meaning can repeat.
A Dart map works the same way. Keys are unique, values do not have to be.
Every Run box on this page runs on the course's Dart runner in your browser.
Maps print with { } and a colon between each key and its value.
What You Will Learn
In this lesson, you will learn:
- What maps and key-value pairs are, and how to create them.
- How to read and change values by key, and handle missing keys.
- Map properties, like
keys,valuesandentries. - How to add, remove, search and loop over entries.
- How to transform maps, nest them, and make maps that never change.
Map Fundamentals
Creating Maps with Map Literals
Map literal = key: value pairs inside { }, separated by commas.
A map of subjects and marks
void main() {
var marks = {'Maths': 92, 'Science': 85, 'English': 78};
print(marks);
print(marks.length);
}
Typed Maps
Typed map = Map<KeyType, ValueType>.
Map<String, int>= text keys, whole-number values.Map<int, String>= number keys, text values.
Different key and value types
void main() {
Map<int, String> rollCall = {1: 'Asha', 2: 'Ravi', 3: 'Priya'};
Map<String, bool> present = {'Asha': true, 'Ravi': false};
print(rollCall[2]);
print(present['Ravi']);
}
Empty Maps
var marks = <String, int>{};
Map<String, int> scores = {};
{} with no type is a Map<dynamic, dynamic>. Add the types so Dart can check what goes in.
Simple lesson: write a map with { key: value }, and give it types like Map<String, int>.
Accessing and Updating Values
Press each button and watch the table:
Look at two things:
- A new key adds a new row.
- An existing key replaces its value. A key can never appear twice.
Accessing Values by Key
marks['Maths'] gives the value stored under the key 'Maths'.
Updating Values and Adding New Pairs
marks['Maths'] = 95;
- If
'Maths'is already a key, its value is replaced. - If it is not, a new pair is added.
Reading, changing and adding
void main() {
var marks = {'Maths': 92, 'Science': 85};
print(marks['Maths']);
marks['Maths'] = 95;
marks['English'] = 78;
print(marks);
}
Handling Missing Keys
A key that is not in the map gives null. It does not crash.
Missing keys give null
void main() {
var marks = {'Maths': 92, 'Science': 85};
print(marks['Art']);
print(marks['Art'] ?? 0);
print(marks.containsKey('Art'));
}
marks['Art']has the typeint?, because the key might be missing (see Null Safety).- Use
?? 0for a default value. - Use
containsKeyto check first.
A map's keys are compared exactly. 'maths' and 'Maths' are two different keys.
Pick one spelling for your keys, and keep to it everywhere in your program.
Simple lesson: map[key] reads or writes one value, and a missing key gives null.
Map Properties
| Property | Gives |
|---|---|
length | how many pairs |
isEmpty / isNotEmpty | whether there are no pairs, or some |
keys | all the keys |
values | all the values |
entries | all the pairs, as MapEntry objects |
Keys, values and entries
void main() {
var marks = {'Maths': 92, 'Science': 85, 'English': 78};
print(marks.keys);
print(marks.values);
print(marks.entries);
print(marks.keys.toList());
print(marks.isNotEmpty);
}
MapEntry = one pair, with a .key and a .value.
keys, values and entries are Iterables, so they print with ( ). Use toList() for a list.
Simple lesson: keys and values give the two halves of a map, and entries gives the pairs.
Adding and Changing Elements
| Method | What it does |
|---|---|
addAll(other) | copies every pair from another map |
putIfAbsent(key, () => v) | adds the pair only if the key is missing |
update(key, (old) => new) | changes one value using the old value |
updateAll((k, v) => new) | changes every value |
Adding and changing pairs
void main() {
var marks = {'Maths': 92, 'Science': 85};
marks.addAll({'English': 78, 'Hindi': 81});
marks.putIfAbsent('Maths', () => 50);
marks.putIfAbsent('Art', () => 70);
marks.update('Science', (old) => old + 5);
print(marks);
marks.updateAll((subject, mark) => mark + 2);
print(marks);
}
putIfAbsent('Maths', ...)did nothing, because'Maths'was already there.updateon a missing key crashes. AddifAbsent: () => valueto give a value instead.
Simple lesson: putIfAbsent adds only new keys, and update changes a value using its old value.
Removing Elements
remove(key)= removes the pair, and gives back its value (ornull).removeWhere((k, v) => test)= removes every pair that passes the test.clear()= removes everything.
Removing pairs
void main() {
var marks = {'Maths': 92, 'Science': 85, 'Art': 30, 'Music': 28};
print(marks.remove('Science'));
print(marks.remove('Dance'));
marks.removeWhere((subject, mark) => mark < 35);
print(marks);
marks.clear();
print(marks);
}
Simple lesson: remove a pair by its key, or remove many with a test.
Searching Maps
containsKey(k)= is this key in the map?containsValue(v)= is this value in the map?
Searching keys and values
void main() {
var marks = {'Maths': 92, 'Science': 85, 'English': 92};
print(marks.containsKey('Maths'));
print(marks.containsKey('Art'));
print(marks.containsValue(85));
print(marks.containsValue(100));
}
containsKey is very fast. containsValue has to check every value, so it is slower on big maps.
Simple lesson: look things up by key whenever you can, because keys are what maps are built for.
Iterating Maps
A map itself is not a list, so you loop over its keys, values or entries.
Four ways to go through a map
void main() {
var marks = {'Maths': 92, 'Science': 85, 'English': 78};
for (var subject in marks.keys) {
print(subject);
}
for (var e in marks.entries) {
print('${e.key} -> ${e.value}');
}
marks.forEach((subject, mark) {
print('$subject: $mark');
});
var total = 0;
for (var m in marks.values) {
total += m;
}
print('Total: $total');
}
forEach on a map gives two values each time: the key and the value.
Counting with a Map
A map is perfect for counting things:
Count the votes
Simple lesson: loop over entries or use forEach to get each key with its value.
Map Transformations
map() and Creating New Maps
map((k, v) => MapEntry(newK, newV)) = a new map, made by changing every pair.
A new map from an old one
void main() {
var marks = {'Maths': 92, 'Science': 85};
var withGrace = marks.map((subject, mark) => MapEntry(subject, mark + 5));
print(withGrace);
var shout = marks.map((subject, mark) => MapEntry(subject.toUpperCase(), mark));
print(shout);
print(marks);
}
The old map is not changed.
Building a Map with for
A map built from a list
void main() {
var names = ['Asha', 'Ravi', 'Priya'];
var nameLengths = {for (var n in names) n: n.length};
print(nameLengths);
}
cast()
cast<K, V>() = treats a map as a map with other types. It is mostly used with JSON data (see File Handling).
Simple lesson: map() with MapEntry builds a new map, and {for ...} builds one from a list.
Useful Map Features
Nested Maps
A value can be another map, or a list:
A map inside a map
void main() {
Map<String, Map<String, int>> reportCards = {
'Asha': {'Maths': 92, 'Science': 88},
'Ravi': {'Maths': 75, 'Science': 81},
};
print(reportCards['Asha']!['Maths']);
for (var student in reportCards.keys) {
print('$student: ${reportCards[student]}');
}
}
reportCards['Asha'] may be null in Dart's eyes, so ! says "this key is there" (see Null Safety).
Maps with Objects and Default Values
- Values can be any type, including your own classes (see Classes).
- For a default when a key is missing, use
map[key] ?? defaultValue.
Simple lesson: maps can hold lists and other maps, so one variable can hold a whole report card.
Unmodifiable Maps
A const map cannot change
void main() {
const passMarks = {'Maths': 35, 'Science': 35};
print(passMarks['Maths']);
passMarks['Art'] = 30;
}
const {...}= fixed before the program runs.Map.unmodifiable(x)= a locked copy, made while it runs.
Easy way to remember
- Find by position: List.
- Find by name: Map.
- Only unique values: Set.
Simple lesson: use const or Map.unmodifiable() when a map must never change.
TL;DR
Map = key-value pairs:
{'Maths': 92}. Keys are unique.- Typed:
Map<String, int>. Empty:<String, int>{}.
- Typed:
Read and write:
map[key]andmap[key] = value.- A missing key gives
null. Use??orcontainsKey.
- A missing key gives
- Properties:
length,keys,values,entries(MapEntrywith.keyand.value). - Change:
addAll,putIfAbsent,update,updateAll,remove,removeWhere,clear. Loop: over
keys,valuesorentries, orforEach((k, v) ...).- Transform:
map((k, v) => MapEntry(...)). Locked:const,Map.unmodifiable().
- Transform:
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
marks[0] for the first pair | Maps have positions | Maps are found by key | null, or a type error. |
marks['Art'] + 5 | Every key exists | A missing key gives null | A null error. Use ?? 0. |
for (var x in marks) | A map is a list | Loop over keys, values or entries | An error. |
update on a missing key | It adds the key | It crashes without ifAbsent | Key not in map. |
| The same key twice in a literal | Both are kept | The last one wins | One pair goes missing. |
marks.map((k, v) => v + 1) | map returns values | It must return a MapEntry | A type error. |
Changing a const map | Only the name is fixed | A const map never changes | An Unsupported operation error. |
Check Yourself
Exercises
What to Remember
- A map stores key-value pairs. Keys are unique, values can repeat.
map[key]reads and writes. A missing key givesnull, so use??orcontainsKey.keys,valuesandentrieslet you loop over a map.forEachgives the key and value.putIfAbsentadds only new keys, andupdatechanges a value from its old value.map()withMapEntrybuilds a new map, andconstmaps never change.
Next: Strings. You will learn to search, cut, change and build text.