100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Lists, Sets, and Maps

Learn Dart's three core collection types, List, Set, and Map, and when to use each for ordered sequences, unique elements, and key-value lookups.

Collections & OOPBeginner9 min readJul 10, 2026
Analogies

Lists, Sets, and Maps

Dart provides three foundational collection types that cover almost every data-organization need: List for ordered sequences, Set for unique unordered collections, and Map for key-value lookups. Choosing the right one up front shapes both the correctness and performance of your code.

🏏

Cricket analogy: A cricket team's batting lineup is itself a structured collection: Dart gives you List for the batting order, Set for players who have scored a century this season (no duplicates), and Map to look up a player's average by name.

Lists: Ordered, Indexable Collections

A List<T> in Dart preserves insertion order and grants constant-time access to any element by its zero-based index. List literals like [1, 2, 3] are growable by default, supporting add(), insert(), and remove(), while List.filled() creates a fixed-length list unless you explicitly pass growable: true.

🏏

Cricket analogy: Virat Kohli's innings-by-innings scores this season form a List<int>, since order matters because you read them chronologically, and calling scores.add(87) after a new match mirrors how Dart lists grow dynamically.

dart
void main() {
  // List: ordered, indexable, growable by default
  List<int> scores = [45, 87, 102, 33];
  scores.add(76);
  scores.insert(2, 99);
  print(scores[0]); // 45
  print(scores.length); // 6

  // List literal with spread operator
  List<int> moreScores = [10, 20, ...scores, 30];
  print(moreScores);

  // Fixed-length list
  var fixed = List<int>.filled(3, 0);
  fixed[0] = 5;
}

Sets: Uniqueness and Fast Membership Checks

A Set<T> stores only unique elements: attempting to add a value already present is silently ignored, and Dart's Set is backed by a hash table, giving average O(1) time for add, remove, and contains, unlike a List's O(n) linear scan for membership checks.

🏏

Cricket analogy: A Set<String> of bowlers who've taken a hat-trick in IPL history automatically discards duplicates, since adding Bumrah's name twice after two separate hat-tricks still leaves exactly one entry, because Set enforces uniqueness.

Dart's Set is backed by a hash table (LinkedHashSet by default via set literals), giving average O(1) time for add, remove, and contains operations, far faster than scanning a List with contains() for large collections.

Maps: Key-Value Storage

A Map<K, V> associates each unique key with a value, letting you resolve a lookup like map[key] in average O(1) time instead of scanning every entry. Map literals use curly braces with colon-separated pairs, and methods like containsKey(), keys, values, and forEach() cover most everyday usage.

🏏

Cricket analogy: A Map<String, int> pairing player names to career centuries lets you look up player['Sachin Tendulkar'] in constant time rather than scanning a whole list of scores to find him.

dart
void main() {
  Map<String, int> playerCenturies = {
    'Sachin Tendulkar': 51,
    'Virat Kohli': 50,
  };

  playerCenturies['Rohit Sharma'] = 32;
  print(playerCenturies['Virat Kohli']); // 50
  print(playerCenturies.containsKey('Dhoni')); // false

  playerCenturies.forEach((name, centuries) {
    print('$name: $centuries centuries');
  });
}

Choosing the Right Collection

Don't reach for List.contains() when checking membership repeatedly in a loop. On a large List this is O(n) per call, turning an O(n) loop into O(n^2). Use a Set for frequent membership checks instead.

  • List<T> preserves insertion order and supports index-based access via [] in O(1) time.
  • Set<T> stores only unique elements and provides O(1) average-case add, remove, and contains via hashing.
  • Map<K, V> stores key-value pairs and resolves lookups by key in O(1) average time rather than scanning.
  • Use the spread operator (...) to combine or embed one collection literal inside another.
  • List.filled() creates a fixed-length list, while list literals like [] create growable lists by default.
  • Prefer Set over List when you need fast membership checks or must guarantee no duplicates.
  • Map.containsKey(), .keys, .values, and .forEach() are core methods for working with key-value data.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#DartStudyNotes#ListsSetsAndMaps#Lists#Sets#Maps#Ordered#DataStructures#StudyNotes#SkillVeris