Sparround

Kolleksiyalar və Iterable

Üç əsas kolleksiya: List (sıralı, təkrarlara icazə verir), Set (unikal elementlər, ==/hashCode əsasında), Map (açar-dəyər). Hər üçü default olaraq LinkedHash... implementasiyasıdır, yəni əlavə olunma sırası qorunur.

Literal yazılışlarda tipi açıq göstərmək vərdiş olmalıdır: boş {} — bu, Map-dir, boş Set üçün <String>{} yazılır. Eyni şəkildə boş [] konteksdən tip çıxara bilmirsə dynamic alır — <User>[] yaz.

Kolleksiyaların konstruksiya sintaksisi Dart-ın ən faydalı xüsusiyyətlərindəndir:

  • collection-if: [if (isAdmin) 'delete']
  • collection-for: [for (final u in users) u.name]
  • spread: [...base, 'extra']
  • null-aware spread: [...?maybeNull]null olsa, sadəcə heç nə əlavə etmir

Bunlar imperativ if/for blokları ilə siyahı yığmaqdan həm qısa, həm də const-a uyğun olduğu üçün üstündür.

YaradılışNəticəNə edilə bilər
`[1, 2, 3]`Growable list`add`, `remove`, `length = n`
`List.filled(3, 0)`Fixed-length listElement dəyişmək olar, `add` — `UnsupportedError`
`List.unmodifiable([1, 2])`Read-only viewHeç bir mutasiya yoxdur
`const [1, 2]`Canonicalise olunmuş immutable listHeç bir mutasiya yoxdur
`someIterable.toList()`Yeni growable listTam mutasiya

Iterable laziness — bu mövzunun ən vacib hissəsidir. map, where, expand, take, skip, followedBy dərhal heç nə hesablamır. Onlar lazy `Iterable` qaytarır: kod yalnız iterasiya başlayanda (for-in, toList(), first, length, fold) işə düşür.

Bundan iki nəticə çıxır:

  • Yan effektlər gözlənilməz vaxtda baş verir. users.map((u) => log(u)); tək başına heç nə çap etmir — çünki heç kim iterasiya etmir.
  • Zəncir hər iterasiyada yenidən icra olunur. final active = users.where(isActive); sonra active.lengthactive.first yazsan, isActive iki dəfə işləyəcək. Əgər mənbə siyahı arada dəyişibsə, iki nəticə fərqli ola bilər.

Qayda: nəticəni bir dəfədən çox istifadə edəcəksənsə, `toList()` (və ya `toSet()`) çağır. Əksinə, böyük mənbədən yalnız ilk uyğun elementi axtarırsansa, laziness sənin xeyrinədir — where(...).first bütün siyahını gəzmir.

Əlavə tələ: lazy Iterable-ı iterasiya edərkən mənbə kolleksiyanı dəyişsən, ConcurrentModificationError alırsan.

MetodQaytarırLazy?Tipik istifadə
`map``Iterable<R>`BəliÇevirmə
`where``Iterable<T>`BəliFiltr
`expand``Iterable<R>`BəliflatMap — iç-içə siyahıları düzləşdirmək
`fold`Tək dəyərXeyrBaşlanğıc dəyəri olan aqreqasiya
`reduce`Tək dəyərXeyrBoş olmayan kolleksiyanın aqreqasiyası
`any` / `every``bool`Xeyr (short-circuit)Şərt yoxlaması
`toList` / `toSet`KolleksiyaXeyrNəticəni materializasiya etmək

Interview ipucu. "map nə qaytarır?" sualı sadə görünür, amma əsl yoxlama laziness-dir. Güclü cavab: "`Iterable`, `List` yox — və o lazy-dir, yəni funksiya iterasiya başlayana qədər çağırılmır. Nəticəni bir neçə dəfə oxuyacağamsa `toList()` edirəm, çünki əks halda zəncir hər dəfə yenidən icra olunur."

Ən çox edilən səhv: map-i JavaScript-dəki kimi dərhal yeni massiv qaytaran metod saymaq. İkinci səhv: foldreduce fərqini bilməmək — reduce boş kolleksiyada StateError atır, fold isə başlanğıc dəyəri olduğu üçün təhlükəsizdir və tip dəyişməyə (List<int>String) imkan verir.

📚 Mənbələr və sənədlər