Skip to content

Beginner · Dart basics · topic 3 of 50 · 30 min

Control flow and collections

Explanation

Dart has if/else, for, for-in, while and do-while loops, and switch, which in Dart 3 can also be an expression that returns a value. The main collections are List (ordered), Set (unique) and Map (key-value). Collection if, collection for and the spread operator ... let you build lists declaratively, a style Flutter uses for lists of widgets.

Decisions

dart
void main() {
  final marks = 72;
  if (marks >= 75) {
    print('Distinction');
  } else if (marks >= 33) {
    print('Pass');
  } else {
    print('Fail');
  }
  final fee = marks >= 90 ? 0 : 500;     // conditional expression
  print(fee);                            // 500
}
condition ? a : b picks one of two values.

Conditions use comparison operators (==, !=, <, >, <=, >=) and logical operators (&& for and, || for or, ! for not). In Dart, a condition must be a real bool; you cannot write if (count) with a number.

Braces after if hold the code to run. Dart allows leaving them out for a single statement, but most style guides (and the Flutter team) recommend braces for anything longer than one short line, so that adding a second line later does not create a bug.

switch, the Dart 3 way

dart
String dayType(int day) => switch (day) {
      1 || 2 || 3 || 4 || 5 => 'Weekday',
      6 || 7 => 'Weekend',
      _ => 'Invalid',
    };

void main() => print(dayType(6));   // Weekend
A switch expression returns a value. || combines patterns; _ matches anything else.

Dart 3 switch statements no longer need break after each case, and the compiler can check that all cases are handled for enums and sealed classes (module 2).

Loops

dart
void main() {
  for (var i = 1; i <= 3; i++) {
    print('Round $i');
  }
  final cities = ['Delhi', 'Agra', 'Jaipur'];
  for (final city in cities) {
    print('Stop: $city');
  }
  var seats = 3;
  while (seats > 0) {
    seats--;
  }
  print(seats);   // 0
}
for-in walks over every item. break leaves a loop; continue skips to the next round.

List, Set and Map

dart
void main() {
  final cart = <String>['milk', 'bread'];       // List: ordered, can repeat
  cart.add('eggs');
  print(cart[0]);              // milk
  print(cart.length);          // 3

  final tags = {'veg', 'spicy', 'veg'};         // Set: unique items
  print(tags);                 // {veg, spicy}

  final stock = <String, int>{'rice': 40, 'dal': 25};   // Map: key -> value
  stock['sugar'] = 10;
  print(stock['rice']);        // 40
  print(stock['ghee']);        // null: missing key
}
<String> and <String, int> are type arguments that say what the collection holds.

Lists are zero-indexed: the first item is cart[0] and the last is cart[cart.length - 1] or cart.last. Writing the type argument (<String>) is optional when Dart can infer it from the values, but it is useful for empty collections, which would otherwise have an unhelpful type.

Collections are themselves typed. A List<String> cannot accept a number, and a Map<String, int> cannot store text as a value. This catches many mistakes early, for example putting a price where a name was expected.

Common methods

dart
void main() {
  final prices = [120, 45, 300, 80];
  final big = prices.where((p) => p >= 100).toList();      // [120, 300]
  final withGst = prices.map((p) => p * 118 ~/ 100).toList();   // [141, 53, 354, 94]
  final total = prices.fold(0, (sum, p) => sum + p);         // 545
  print('$big $withGst $total ${prices.contains(45)}');
}
where filters, map transforms (both are lazy until toList), fold combines into one value.

Collection if, for and spread

Dart lets you put if and for directly inside a list literal, and spread another list into it with .... This is used constantly in Flutter to build lists of widgets.

dart
void main() {
  final isMember = true;
  final extras = ['Pickle', 'Papad'];
  final thali = [
    'Rice',
    'Dal',
    if (isMember) 'Sweet',                 // collection if
    for (final e in extras) 'Extra: $e',   // collection for
    ...['Buttermilk'],                     // spread
  ];
  print(thali);
}
Prints: [Rice, Dal, Sweet, Extra: Pickle, Extra: Papad, Buttermilk]
Think of it like this: A List is like a queue at a ration shop (order matters, people can appear twice), a Set is like a guest list (each name once), and a Map is like a register where each roll number points to one student's name.

Common mistakes

  • Forgetting .toList() after where or map when you need a List: they return a lazy Iterable.
  • Reading list[i] with an index that may be out of range: RangeError. Check the length first.
  • Forgetting that map[key] can be null when the key is missing.
  • Using a plain list and expecting duplicates to disappear. Use a Set.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Control flow and collections · 1/6

final fee = marks >= 90 ? 0 : 500;

if and else make decisions. The question mark colon operator picks one of two values.

Prefer a video by a teacher? Find free videos on “dart control flow switch expression list map set collection if for spread” on YouTube ↗

In real life: A simple menu builder

A café's ordering screen shows today's menu: regular items, a "Chef's special" only on weekends, and all seasonal drinks from a list. The code that builds the menu uses collection if and for, exactly the style Flutter screens use to build their widget lists.

dart
void main() {
  final isWeekend = DateTime.now().weekday >= 6;
  final seasonal = ['Mango shake', 'Kokum sharbat'];
  final menu = [
    'Masala chai',
    'Filter coffee',
    if (isWeekend) "Chef's special thali",
    for (final d in seasonal) d,
  ];
  for (final (i, item) in menu.indexed) {
    print('${i + 1}. $item');
  }
}
menu.indexed (Dart 3) gives (index, item) records.

Practice (0/3 done)

Task 1 · Question

What does this print? final nums = [4, 9, 2, 7]; print(nums.where((n) => n > 3).map((n) => n * 2).toList());

Task 2 · Question

What does this print? final show = false; final items = ['a', if (show) 'b', 'c']; print(items.length);

Task 3 · Practice

Write a program with a Map of student names to marks. Print each student with "Pass" or "Fail" (33 and above passes) using a for-in loop over entries, the class average with fold, and a List of toppers (75+) built with where and toList.

Quick quiz

Question 1

1.Which collection keeps only unique values?

Question 2

2.What does where return before toList()?

Question 3

3.In a Dart 3 switch expression, what does _ mean?

Question 4

4.What does the spread operator ... do in a list literal?

Read more (free)

Before this, learn

This topic builds on these. If something here feels new, open them first.

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which collection keeps only unique values?

Answer: Set

Sets ignore duplicates.

What does where return before toList()?

Answer: A lazy Iterable

Call toList() to get a List.

In a Dart 3 switch expression, what does _ mean?

Answer: Match anything else (default)

The wildcard pattern.

What does the spread operator ... do in a list literal?

Answer: Inserts all items of another collection

...other adds each element.

What is special about loop compared to while?Related

Answer: It can return a value with break value

loop can hand a value out with break, which makes it an expression.

From Control flow: if, loop, while and for

What does _ mean in a switch expression?Related

Answer: Match anything else (the discard)

The discard pattern _ matches any value not matched earlier.

From Decisions: if, else, switch and switch expressions

Which type can NOT be used in a switch?Related

Answer: std::string

switch needs an integral or enum value. Use if / else if for strings.

From Operators and decisions: if, else and switch

How do you make one switch case match both 1 and 2?Related

Answer: case 1, 2:

List several values separated by commas in one case.

From Decisions with if and switch

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Dart basics” before its exam: Functions.
  2. Module 1 exam: Dart basics · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Null safety and object-oriented Dart. 50 topics left in the course before the final exam.

← Previous: Your first Dart program, variables and types