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.

Create a free account to save this page, take notes and track your progress. Sign in

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

Cart totals, grouping and a declarative receipt
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 const list. const collections are immutable; copy with [...list] first.
  • map[key] is nullable. Handle the missing case (?? 0) or use update/putIfAbsent.
  • sort() returns void. It sorts in place; the cascade ..sort() keeps the expression returning the list.
  • Lazy iterables evaluated repeatedly. Store .toList() if you'll iterate a where/map result several times.

Key points

  • List, Map, Set with where, map, fold, any, every, sort.
  • Collection if, collection for and ...spread build lists and maps declaratively.
  • update(..., ifAbsent:) and putIfAbsent for 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.

Was this page helpful?