Lists & Collections
Organizing Groups of Data
Open interactive version (quiz + challenge)Real-world analogy
A List is like a row of school lockers -- each has a number (index) starting from 0, and each holds one item. A Map is like a dictionary -- you look up a word (key) to find its meaning (value). A Set is like a bag of marbles where every marble must be unique -- no duplicates allowed!
What is it?
Dart has three main collection types: List (ordered, indexed, allows duplicates), Map (key-value pairs, unique keys), and Set (unordered, unique values). Lists are the most common. All three support iteration, transformation, and null-safe access.
Real-world relevance
Lists of products in a shopping app, Maps of user profiles keyed by ID, Sets of unique tags or categories. Collections are the backbone of data management in every app. The team_mvp_kit project uses List for API responses, Map for JSON parsing, and Set for unique identifiers.
Key points
- Creating Lists — A List is an ordered collection of items. Create with square brackets []. Items are accessed by index starting at 0. Lists can grow and shrink. You can specify the type with List for safety.
- Adding and Removing — Use add() to append one item, addAll() to append multiple, insert() to add at a specific position. Remove with remove() (by value), removeAt() (by index), removeLast(), and clear() (remove all).
- List Methods — Lists have many useful methods: contains() checks membership, indexOf() finds position, sort() orders items, reversed returns a reversed view, sublist() extracts a portion, and join() combines into a string.
- map, filter, where — map() transforms each item. where() (Dart's filter) keeps items that pass a test. These return Iterables, so call .toList() to get a List back. These functional methods are powerful and widely used.
- Maps - Key-Value Pairs — A Map stores key-value pairs. Each key is unique and maps to a value. Create with curly braces {}. Access values with map[key]. Perfect for lookups, configurations, and structured data.
- Map Operations — Add entries with map[key] = value. Remove with remove(). Check existence with containsKey() and containsValue(). Get all keys with .keys and all values with .values.
- Sets - Unique Collections — A Set is an unordered collection with NO duplicates. Adding an existing item is silently ignored. Perfect for tracking unique tags, visited pages, or selected items.
- Spread Operator and Collection If/For — The spread operator (...) merges collections. Collection if adds items conditionally. Collection for adds items from a loop. These make building collections clean and expressive.
- Null-Safe Collection Access — Use the ?[] operator for null-safe map access and firstOrNull/lastOrNull for safe list access. This prevents crashes when dealing with potentially missing data.
Code example
void main() {
// === LISTS ===
var fruits = ['apple', 'banana', 'cherry', 'date'];
// Access and modify
print(fruits[0]); // 'apple'
fruits.add('elderberry');
fruits.removeAt(1); // removes 'banana'
print(fruits); // [apple, cherry, date, elderberry]
// Transform with map and where
var upperFruits = fruits.map((f) => f.toUpperCase()).toList();
print(upperFruits); // [APPLE, CHERRY, DATE, ELDERBERRY]
var longNames = fruits.where((f) => f.length > 5).toList();
print(longNames); // [cherry, elderberry]
// === MAPS ===
var student = <String, dynamic>{
'name': 'Ali',
'age': 14,
'grades': [90, 85, 92],
};
print(student['name']); // 'Ali'
student['school'] = 'ABC Academy'; // add new key
print(student.keys.toList());
// Iterate a Map
student.forEach((key, value) {
print('$key: $value');
});
// === SETS ===
var visited = <String>{'home', 'about', 'contact'};
visited.add('home'); // ignored - duplicate!
print(visited.length); // 3
// Collection if and for
var isVIP = true;
var menu = [
'Dashboard',
'Profile',
if (isVIP) 'VIP Lounge',
];
print(menu);
var doubled = [for (var i = 1; i <= 5; i++) i * 2];
print(doubled); // [2, 4, 6, 8, 10]
}Line-by-line walkthrough
- 1. The main function starts
- 2. A comment header for the Lists section
- 3. Creating a list of four fruits
- 4.
- 5. A comment for access and modify operations
- 6. Accessing the first item at index 0 -- prints 'apple'
- 7. Adding 'elderberry' to the end of the list
- 8. Removing the item at index 1 (banana)
- 9. Printing the updated list
- 10.
- 11. A comment for transformations
- 12. map() creates a new list with each fruit in UPPERCASE
- 13. Printing the uppercased list
- 14.
- 15. where() keeps only fruits with more than 5 characters
- 16. Printing the filtered result
- 17.
- 18. A comment header for the Maps section
- 19. Creating a Map with String keys and dynamic values
- 20. Storing the name 'Ali'
- 21. Storing the age 14
- 22. Storing a list of grades as a value
- 23. Closing the map literal
- 24.
- 25. Accessing the 'name' key -- prints 'Ali'
- 26. Adding a new key 'school' with value 'ABC Academy'
- 27. Printing all keys of the map
- 28.
- 29. A comment for iterating a Map
- 30. forEach loops through every key-value pair
- 31. Printing each key and value using string interpolation
- 32. Closing the forEach
- 33.
- 34. A comment header for the Sets section
- 35. Creating a Set with three unique page names
- 36. Adding 'home' again -- ignored because it already exists!
- 37. Printing the length -- still 3, duplicate was ignored
- 38.
- 39. A comment for collection if and for
- 40. A boolean flag for VIP status
- 41. Creating a list with collection if
- 42. Always includes 'Dashboard'
- 43. Always includes 'Profile'
- 44. Only includes 'VIP Lounge' if isVIP is true
- 45. Closing the list
- 46. Printing the menu
- 47.
- 48. Collection for generates a list of doubled numbers
- 49. Printing the result: [2, 4, 6, 8, 10]
- 50. Closing the main function
Spot the bug
void main() {
var fruits = ['apple', 'banana'];
print(fruits[2]);
var scores = {'math': 90, 'science': 85};
scores.add('english', 92);
}Need a hint?
Check the list index and the Map method for adding entries...
Show answer
Two bugs: (1) fruits[2] causes a RangeError because the list only has indices 0 and 1. Fix: use fruits[1] or add another item first. (2) Maps do not have an add() method. Fix: use scores['english'] = 92; to add a key-value pair.
Explain like I'm 5
Imagine your school bag. A List is like a row of pockets numbered 0, 1, 2, 3 -- each holding something, and you can find things by their pocket number. A Map is like labels on each pocket: 'lunch' pocket has your sandwich, 'books' pocket has your textbook. A Set is like a sticker collection where you cannot have two of the same sticker -- if you try to add one you already have, it just does nothing!
Fun fact
Dart Lists are actually implemented as growable arrays internally. When you add items beyond the current capacity, Dart creates a new larger array and copies everything over. This is why adding to the end (add) is fast on average, but inserting at the beginning (insert(0, x)) is slow for large lists!
Hands-on challenge
Create a Map of 5 countries and their capitals. Write code to: (1) Print all country names. (2) Check if 'Japan' is in the map. (3) Add a new country. (4) Remove a country. (5) Print all capitals sorted alphabetically.
More resources
- Dart Collections (Dart Official)
- Dart List Class (Dart API)
- Iterable Collections (Dart Official)