Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
Dizi · 16/64 Dart Türkçe Tutorial
- Bölüm 1 — Konu 1: Dart Nedir, Nerede Kullanılır, Neden Flutter Bu Dili Seçti
- Bölüm 1 — Konu 2: Ortam Kurulumu (Dart SDK, DartPad, Terminal ile Çalıştırma)
- Bölüm 1 — Konu 3: İlk Program (`main()`, `print()`, Dosya Yapısı)
- Bölüm 1 — Konu 4: Yorum Satırları, Temel Sözdizimi Kuralları
- Bölüm 2 — Konu 5: Değişken Tanımlama — `var`, `final`, `const` Farkı
- Bölüm 2 — Konu 6: Temel Tipler — `int`, `double`, `String`, `bool`
- Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme
- Bölüm 2 — Konu 8: `dynamic` ve `Object` — Ne Zaman Kullanılır, Ne Zaman Kaçınılır
- Bölüm 2 — Konu 9: Null Safety Temelleri (`?`, `!`, `late`'e Giriş)
- Bölüm 3 — Konu 10: Aritmetik, Atama, Karşılaştırma, Mantıksal Operatörler
- Bölüm 3 — Konu 11: `if / else if / else`
- Bölüm 3 — Konu 12: `switch` / `switch expression` (Modern Dart)
- Bölüm 3 — Konu 13: Ternary Operatör, `??`, `??=`, `?.`
- Bölüm 3 — Konu 14: `for`, `while`, `do-while` Döngüleri
- Bölüm 4 — Konu 16: `List` — Oluşturma, Erişim, Temel Metodlar
- Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
- Bölüm 4 — Konu 18: `Map` — Key-Value Yapılar
- Bölüm 4 — Konu 19: Koleksiyon Üzerinde `for-in`, `forEach`
- Bölüm 4 — Konu 20: Spread Operatörü (`...`, `...?`) ve Collection If/For
- Bölüm 5 — Konu 21: Fonksiyon Tanımlama, Parametreler (Positional, Named, Optional)
- Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)
- Bölüm 5 — Konu 23: Arrow Function (`=>`) Sözdizimi
- Bölüm 5 — Konu 24: Fonksiyonlar Birinci Sınıf Vatandaş — Değişkene Atama, Parametre Olarak Geçme
- Bölüm 5 — Konu 25: Anonim Fonksiyonlar ve Closure Kavramı (Derinlemesine)
- Bölüm 5 — Konu 26: Recursion (Özyineleme)
- Bölüm 6 — Konu 27: Class Tanımlama, Constructor (Varsayılan, Named, Factory)
- Bölüm 6 — Konu 28: Alanlar (Fields), Metodlar, `this` Kullanımı (Derinlemesine)
- Bölüm 6 — Konu 29: Initializer List, Constructor Kısayolları (Derinlemesine)
- Bölüm 6 — Konu 30: Getter / Setter
- Bölüm 6 — Konu 31: Statik Üyeler (`static`)
- Bölüm 7 — Konu 32: Kalıtım (`extends`), `super` Kullanımı
- Bölüm 7 — Konu 33: Metod Override Etme, `@override`
- Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
- Bölüm 7 — Konu 35: Interface Mantığı (`implements`)
- Bölüm 7 — Konu 36: Mixin (`with`)
- Bölüm 7 — Konu 37: `enum` — Basit ve Gelişmiş (Metotlu Enum'lar)
- Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
- Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma
- Bölüm 8 — Konu 40: Sound Null Safety Derinlemesine — `late`, `required`, Non-Nullable Varsayılan Davranış
- Bölüm 8 — Konu 41: `assert` ile Geliştirme Zamanı Kontrolleri
- Bölüm 9 — Konu 42: Generic Sınıflar ve Fonksiyonlar
- Bölüm 9 — Konu 43: Generic Sınırlamalar (`<T extends ...>`)
- Bölüm 9 — Konu 44: Dart'ın Built-in Generic Koleksiyonları Nasıl Çalışır
- Bölüm 10 — Konu 45: `Future` Kavramı, `async`/`await`
- Bölüm 10 — Konu 46: `Future.then`, Hata Yönetimi (`catchError`)
- Bölüm 10 — Konu 47: `Stream` Temelleri, `async*`, `yield`
- Bölüm 10 — Konu 48: `StreamController`, Broadcast Stream
- Bölüm 11 — Konu 49: `map`, `where`, `reduce`, `fold`
- Bölüm 11 — Konu 50: `sort`, Custom Comparator ile Sıralama
- Bölüm 11 — Konu 51: Iterable Kavramı Derinlemesine (Lazy Evaluation)
- Bölüm 11 — Konu 52: Cascade Notasyonu (`..`)
- Bölüm 12 — Konu 53: `pubspec.yaml`, pub.dev'den Paket Ekleme
- Bölüm 12 — Konu 54: Kütüphane Oluşturma, `import`/`export`, `part`/`part of`
- Bölüm 12 — Konu 55: Dart'ta Test Yazımı (`test` Paketi, Unit Test Mantığı)
- Bölüm 12 — Konu 56: Extension Methods
- Bölüm 12 — Konu 57: Dart'ın Derleme Modelleri (JIT vs AOT) ve Bunun Flutter'a Etkisi
- Bölüm 13 — Konu 59: Dart 3 Pattern Matching — Records, Destructuring, Sealed Classes, Exhaustive Switch
- Bölüm 13 — Konu 60: `Never` Tipi, `covariant` ve Generic Variance Detayları
- Bölüm 13 — Konu 61: Event Loop Derinlemesine — Microtask Queue vs Event Queue
- Bölüm 13 — Konu 62: Memory Model & Performans — Garbage Collection, `const` Nesnelerin Bellek Avantajı
- Bölüm 13 — Konu 63: Isolate'ler Arası Mesajlaşmanın Maliyeti ve `compute()`'un İç İşleyişi
- Bölüm 13 — Konu 64: FFI (Foreign Function Interface) — C Koduna Erişim
- Bölüm 13 — Konu 65: Sunucu Tarafında Dart — `dart:io`, `shelf` Paketiyle Basit Bir Backend/CLI Aracı Yazma
- Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi
İçindekiler 10 başlık
Set Nedir?
Set, List'e benzer ama iki kritik farkla: her eleman benzersizdir (tekrar edemez) ve sırasızdır (elemanların garantili bir sırası yoktur — Dart'ın LinkedHashSet implementasyonu pratikte ekleme sırasını korur ama bu, List'in indeksli erişimiyle aynı garanti değildir).
Set Oluşturma
void main() {
Set<String> renkler = {"Kırmızı", "Mavi", "Yeşil"};
print(renkler); // {Kırmızı, Mavi, Yeşil}
var sayilar = {1, 2, 3}; // tip çıkarımı ile Set<int>
print(sayilar);
}Dikkat et — Set de süslü parantez { } kullanır, tıpkı bir sonraki konuda göreceğimiz Map gibi. Dart, boş bir {} gördüğünde bunu varsayılan olarak Map sayar (çünkü Map daha yaygın kullanılır), bu yüzden boş bir Set oluştururken tipi açıkça belirtmen gerekir:
void main() {
var boşSet = <String>{}; // Set<String> olarak belirtilmeli
print(boşSet); // {}
print(boşSet.runtimeType); // Set<String>
var boşMap = {}; // bu varsayılan olarak Map<dynamic, dynamic> olur
print(boşMap.runtimeType); // Map<dynamic, dynamic>
}Otomatik Tekrar Eleme (Deduplication)
Set'in en belirgin özelliği budur:
void main() {
Set<String> renkler = {"Kırmızı", "Mavi", "Kırmızı", "Yeşil", "Mavi"};
print(renkler); // {Kırmızı, Mavi, Yeşil} — tekrarlar otomatik silinir!
print(renkler.length); // 3
}Bir listeyi Set'e çevirerek tekrar eden elemanları temizlemek, çok yaygın bir kullanım kalıbıdır:
void main() {
List<String> isimlerListesi = ["Ali", "Veli", "Ali", "Ayşe", "Veli"];
Set<String> tekrarsizIsimler = isimlerListesi.toSet();
print(tekrarsizIsimler); // {Ali, Veli, Ayşe}
// İstersen tekrar listeye çevirebilirsin
List<String> temizListe = tekrarsizIsimler.toList();
print(temizListe); // [Ali, Veli, Ayşe]
}Eleman Ekleme ve Çıkarma
void main() {
Set<String> renkler = {"Kırmızı", "Mavi"};
renkler.add("Yeşil");
print(renkler); // {Kırmızı, Mavi, Yeşil}
renkler.add("Kırmızı"); // zaten var, hiçbir şey olmaz (hata da vermez)
print(renkler); // {Kırmızı, Mavi, Yeşil} — değişmedi
renkler.remove("Mavi");
print(renkler); // {Kırmızı, Yeşil}
}Neden List Değil de Set İndeksle Erişilemiyor?
void main() {
Set<String> renkler = {"Kırmızı", "Mavi", "Yeşil"};
print(renkler[0]); // ❌ HATA! Set'te indeksli erişim yoktur
}Bu, Set'in doğasından kaynaklanır — sırası garanti edilmediği (ve öncelik olarak "hızlı arama" için optimize edildiği) için, "0. eleman" gibi bir kavram anlamlı değildir. Eğer elemanlara erişmen gerekiyorsa, for-in ile gezinebilir veya .toList() ile listeye çevirip indeksli erişim kazanabilirsin.
Küme (Set) Matematik Operasyonları
Set, matematikteki küme kavramından geliyor, bu yüzden küme işlemlerini de destekler:
void main() {
Set<int> setA = {1, 2, 3, 4};
Set<int> setB = {3, 4, 5, 6};
// Kesişim (intersection) — ikisinde de olanlar
print(setA.intersection(setB)); // {3, 4}
// Birleşim (union) — ikisinde de olan, tekrar etmeyen tüm elemanlar
print(setA.union(setB)); // {1, 2, 3, 4, 5, 6}
// Fark (difference) — setA'da olup setB'de olmayanlar
print(setA.difference(setB)); // {1, 2}
}Bu operasyonlar, örneğin "iki kullanıcı grubunun ortak ilgi alanlarını bulmak" veya "bir listeden başka bir listede olmayan elemanları çıkarmak" gibi senaryolarda çok kullanışlıdır — bunları List ile yapmak çok daha fazla manuel kod gerektirirdi.
Arama ve Kontrol Metodları
void main() {
Set<String> renkler = {"Kırmızı", "Mavi", "Yeşil"};
print(renkler.contains("Mavi")); // true
print(renkler.isEmpty); // false
print(renkler.isNotEmpty); // true
print(renkler.length); // 3
}Önemli performans notu: Set.contains(), ortalama olarak List.contains()'ten çok daha hızlıdır — özellikle büyük veri kümelerinde. List.contains(), elemanı bulmak için listeyi baştan sona taramak zorundadır (O(n) karmaşıklık), Set.contains() ise iç yapısı (hash tabanlı) sayesinde bunu ortalama sabit zamanda yapabilir (O(1)). Bu yüzden "bu eleman bu koleksiyonda var mı" kontrolünü sık sık yapacaksan ve sıralama/tekrar önemli değilse, Set performans açısından daha iyi bir seçimdir.
List mi Set mi? — Karar Verme
| Kriter | List |
Set |
|---|---|---|
| Sıra önemli mi? | ✅ Evet, korunur | ❌ Garanti yok |
| Tekrar eden elemanlar olmalı mı? | ✅ Olabilir | ❌ Otomatik silinir |
| İndeksle erişim gerekiyor mu? | ✅ liste[0] |
❌ Yok |
| Sık "içinde var mı" kontrolü yapılacak mı? | Yavaş (O(n)) | Hızlı (O(1) ortalama) |
| Küme işlemleri (kesişim, birleşim) gerekiyor mu? | ❌ Manuel yazman gerekir | ✅ Doğrudan destekli |
🎯 Bu Dersten Çıkarılması Gerekenler
Set: benzersiz elemanlar tutar, sırası garanti edilmez, indeksle erişilemez.List.toSet()ile tekrar eden elemanları temizleyebilirsin,.toList()ile geri listeye çevirebilirsin.- Küme operasyonları:
intersection(kesişim),union(birleşim),difference(fark). Set.contains(), büyük veri kümelerindeList.contains()'ten performans olarak daha avantajlıdır.- Boş bir
Setoluştururken tip belirtmen gerekir (<String>{}), yoksa Dart bunuMapsanır.
📝 Ödevler
- [ ] Tekrar eden isimler içeren bir liste oluştur,
.toSet()ile tekrarları temizle, sonra tekrar.toList()yap. - [ ] İki farklı
Set<int>oluştur (bazı ortak elemanlarla),intersection,unionvedifferencesonuçlarını sırayla yazdır ve yorumla. - [ ]
SetveListile aynı 1000 elemanlı bir koleksiyonda.contains()çağırıp (performans farkını gözlemlemek için yorumla, ölçmesi bu seviyede zor olabilir ama mantığını açıkla). - [ ] Bir öğrenci sınıfındaki (varsayımsal) ders seçimlerini
Set<String>ile modelle, iki öğrencinin ortak dersleriniintersectionile bul.
Sıradaki konu: Bölüm 4 — Konu 18: Map — Key-Value Yapılar