# Lists, Sets, Maps and Iterables — Dart

Source: https://www.skillbyai.com/en/dart/n-collections

> Work with Dart collections and lazy Iterable operations.

## Core collections

**`List<T>`** is an ordered, indexable collection (growable by default; `List.unmodifiable` and `const` lists are not). **`Set<T>`** holds unique elements (a `LinkedHashSet` preserving insertion order by default), and **`Map<K, V>`** maps keys to values (a `LinkedHashMap` by default, also insertion-ordered). All are generic, so the analyser checks element types. Most transformation methods live on **`Iterable`** and are **lazy**: `map`, `where`, `expand`, `skip` and `take` return iterables that compute elements only when iterated, so call `toList()` or `toSet()` when you need a concrete, reusable collection, and avoid iterating an expensive lazy chain several times. Other useful members: `fold`, `reduce`, `any`, `every`, `firstWhere` (with `orElse`), `whereType<T>()`, `sorted` via `toList()..sort(...)`, `asMap`, `indexed` (Dart 3, yields index and element records), and for maps `entries`, `putIfAbsent`, `update` and `map`. Index access out of range throws a `RangeError`. The `collection` package adds helpers such as `groupBy`, `firstWhereOrNull` and deep equality.

## Collections in everyday code

Lazy iterables, grouping by hand and map updates.

```dart
void main() {
  final orders = [
    (id: 'o1', city: 'Pune', total: 1200.0),
    (id: 'o2', city: 'Delhi', total: 300.0),
    (id: 'o3', city: 'Pune', total: 800.0),
  ];

  final bigIds = orders.where((o) => o.total >= 500).map((o) => o.id).toList();   // [o1, o3]
  final revenue = orders.fold<double>(0, (sum, o) => sum + o.total);            // 2300.0

  final byCity = <String, double>{};
  for (final o in orders) {
    byCity.update(o.city, (v) => v + o.total, ifAbsent: () => o.total);
  }
  print(byCity);                                 // {Pune: 2000.0, Delhi: 300.0}

  final cities = orders.map((o) => o.city).toSet();   // {Pune, Delhi}
  final sorted = orders.toList()..sort((a, b) => b.total.compareTo(a.total));

  for (final (index, o) in orders.indexed) {      // Dart 3 record destructuring
    print('$index: ${o.id}');
  }

  final first = orders.firstWhere((o) => o.city == 'Mumbai', orElse: () => orders.first);
}
```

## map and where are lazy

`orders.where(...)` does nothing until you iterate it, and iterating twice runs the filter twice. Call `toList()` once if you will reuse the result, especially when the callback is expensive or has side effects.

**Quiz:** What does Iterable.where return?

- [x] A lazy Iterable whose elements are computed when iterated
- [ ] A new List immediately
- [ ] A Set
- [ ] A Future

*Answer:* A lazy Iterable whose elements are computed when iterated. where and map are lazy; convert with toList() for a concrete collection.
