Dart Fundamentals: The Language Behind Flutter · Dart Basics: Variables, Null Safety, Functions and Collections
Lists, Maps and Sets with Collection If, For and Spread
Work with List, Map and Set, transform them with where/map/fold, and build them declaratively with collection if, collection for and the spread operator, the style Flutter UIs use everywhere.
What you'll build
A shopping cart summary: a list of items, a map of prices, a set of tags, totals with fold, grouping, and a receipt built with collection if, for and spread.
The idea
List<T>: ordered, indexable ([1, 2, 3],add,removeAt,length).Map<K, V>: key-value pairs ({'apple': 0.5},map['apple']returns a nullable value,putIfAbsent,update,entries).Set<T>: unique values ({'a', 'b'},contains,union,intersection).
Transform with where (filter), map, fold (reduce with an initial value), any, every, firstWhere, and sort with sort((a, b) => ...).
Build collections declaratively:
final lines = [
'Receipt',
for (final item in items) '${item.name}: ${item.price}',
if (discount > 0) 'Discount: -$discount',
...footerLines,
];
This is exactly how Flutter builds widget lists, so it's worth getting comfortable with.
The code
class Item {
final String name;
final String category;
final double price;
final int qty;
const Item(this.name, this.category, this.price, this.qty);
double get total => price * qty;
}
void main() {
const cart = [
Item('Coffee beans', 'grocery', 12.50, 2),
Item('Mug', 'kitchen', 8.00, 1),
Item('Oat milk', 'grocery', 2.20, 3),
Item('Kettle', 'kitchen', 34.90, 1),
];
final memberTags = {'member', 'newsletter'};
final subtotal = cart.fold<double>(0, (sum, item) => sum + item.total);
final isMember = memberTags.contains('member');
final discount = isMember ? subtotal * 0.1 : 0.0;
final byCategory = <String, double>{};
for (final item in cart) {
byCategory.update(item.category, (v) => v + item.total, ifAbsent: () => item.total);
}
final expensive = cart.where((i) => i.price > 10).map((i) => i.name).toList();
final sorted = [...cart]..sort((a, b) => b.total.compareTo(a.total));
final receipt = [
'RECEIPT',
for (final item in cart) '${item.name.padRight(13)} x${item.qty} ${item.total.toStringAsFixed(2).padLeft(6)}',
'Subtotal'.padRight(17) + subtotal.toStringAsFixed(2).padLeft(6),
if (discount > 0) 'Member -10%'.padRight(17) + (-discount).toStringAsFixed(2).padLeft(6),
'Total'.padRight(17) + (subtotal - discount).toStringAsFixed(2).padLeft(6),
];
print(receipt.join('\n'));
print('by category: ${byCategory.map((k, v) => MapEntry(k, v.toStringAsFixed(2)))}');
print('over 10: $expensive');
print('biggest line: ${sorted.first.name}');
print('all in stock-friendly quantities: ${cart.every((i) => i.qty <= 3)}');
print('tags: ${memberTags.union({'vip'})}');
}
Output
RECEIPT
Coffee beans x2 25.00
Mug x1 8.00
Oat milk x3 6.60
Kettle x1 34.90
Subtotal 74.50
Member -10% -7.45
Total 67.05
by category: {grocery: 31.60, kitchen: 42.90}
over 10: [Coffee beans, Kettle]
biggest line: Kettle
all in stock-friendly quantities: true
tags: {member, newsletter, vip}Run this on your computer — see “Get Started” for setup.
Common mistakes
- Modifying a
constlist.constcollections are immutable; copy with[...list]first. map[key]is nullable. Handle the missing case (?? 0) or useupdate/putIfAbsent.sort()returnsvoid. It sorts in place; the cascade..sort()keeps the expression returning the list.- Lazy iterables evaluated repeatedly. Store
.toList()if you'll iterate awhere/mapresult several times.
Key points
List,Map,Setwithwhere,map,fold,any,every,sort.- Collection
if, collectionforand...spreadbuild lists and maps declaratively. update(..., ifAbsent:)andputIfAbsentfor grouping and counting.- Cascades (
..) call several methods on the same object.
Further reading: Collections, Iterable collections.
Practice questions
What are collection if and collection for in Dart?
Answer
Syntax inside list, set and map literals that conditionally includes elements (if (cond) value) or generates elements from a loop (for (x in xs) value). Flutter uses them to build widget lists declaratively.
Why does `myList.sort()` not return the sorted list, and how do you sort inline?
Answer
sort sorts in place and returns void. Use the cascade operator to get the list back: final sorted = [...items]..sort(compare);
Open in the app to mark lessons complete, take notes and track your progress.