↑↓ seç · Enter aç · Esc kapat

Mutlu Tekin
Mutlu Tekin
← Yazılar

Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı

2 dk okuma #dart
Dizi · 16/64 Dart Türkçe Tutorial
  1. Bölüm 1 — Konu 1: Dart Nedir, Nerede Kullanılır, Neden Flutter Bu Dili Seçti
  2. Bölüm 1 — Konu 2: Ortam Kurulumu (Dart SDK, DartPad, Terminal ile Çalıştırma)
  3. Bölüm 1 — Konu 3: İlk Program (`main()`, `print()`, Dosya Yapısı)
  4. Bölüm 1 — Konu 4: Yorum Satırları, Temel Sözdizimi Kuralları
  5. Bölüm 2 — Konu 5: Değişken Tanımlama — `var`, `final`, `const` Farkı
  6. Bölüm 2 — Konu 6: Temel Tipler — `int`, `double`, `String`, `bool`
  7. Bölüm 2 — Konu 7: Tip Çıkarımı (Type Inference) ve Açık Tip Belirtme
  8. Bölüm 2 — Konu 8: `dynamic` ve `Object` — Ne Zaman Kullanılır, Ne Zaman Kaçınılır
  9. Bölüm 2 — Konu 9: Null Safety Temelleri (`?`, `!`, `late`'e Giriş)
  10. Bölüm 3 — Konu 10: Aritmetik, Atama, Karşılaştırma, Mantıksal Operatörler
  11. Bölüm 3 — Konu 11: `if / else if / else`
  12. Bölüm 3 — Konu 12: `switch` / `switch expression` (Modern Dart)
  13. Bölüm 3 — Konu 13: Ternary Operatör, `??`, `??=`, `?.`
  14. Bölüm 3 — Konu 14: `for`, `while`, `do-while` Döngüleri
  15. Bölüm 4 — Konu 16: `List` — Oluşturma, Erişim, Temel Metodlar
  16. Bölüm 4 — Konu 17: `Set` — Benzersiz Eleman Mantığı
  17. Bölüm 4 — Konu 18: `Map` — Key-Value Yapılar
  18. Bölüm 4 — Konu 19: Koleksiyon Üzerinde `for-in`, `forEach`
  19. Bölüm 4 — Konu 20: Spread Operatörü (`...`, `...?`) ve Collection If/For
  20. Bölüm 5 — Konu 21: Fonksiyon Tanımlama, Parametreler (Positional, Named, Optional)
  21. Bölüm 5 — Konu 22: Varsayılan Parametre Değerleri (Derinlemesine)
  22. Bölüm 5 — Konu 23: Arrow Function (`=>`) Sözdizimi
  23. Bölüm 5 — Konu 24: Fonksiyonlar Birinci Sınıf Vatandaş — Değişkene Atama, Parametre Olarak Geçme
  24. Bölüm 5 — Konu 25: Anonim Fonksiyonlar ve Closure Kavramı (Derinlemesine)
  25. Bölüm 5 — Konu 26: Recursion (Özyineleme)
  26. Bölüm 6 — Konu 27: Class Tanımlama, Constructor (Varsayılan, Named, Factory)
  27. Bölüm 6 — Konu 28: Alanlar (Fields), Metodlar, `this` Kullanımı (Derinlemesine)
  28. Bölüm 6 — Konu 29: Initializer List, Constructor Kısayolları (Derinlemesine)
  29. Bölüm 6 — Konu 30: Getter / Setter
  30. Bölüm 6 — Konu 31: Statik Üyeler (`static`)
  31. Bölüm 7 — Konu 32: Kalıtım (`extends`), `super` Kullanımı
  32. Bölüm 7 — Konu 33: Metod Override Etme, `@override`
  33. Bölüm 7 — Konu 34: Soyut Sınıflar (`abstract class`)
  34. Bölüm 7 — Konu 35: Interface Mantığı (`implements`)
  35. Bölüm 7 — Konu 36: Mixin (`with`)
  36. Bölüm 7 — Konu 37: `enum` — Basit ve Gelişmiş (Metotlu Enum'lar)
  37. Bölüm 8 — Konu 38: `try / catch / finally`, `throw`
  38. Bölüm 8 — Konu 39: Özel Exception Sınıfları Yazma
  39. Bölüm 8 — Konu 40: Sound Null Safety Derinlemesine — `late`, `required`, Non-Nullable Varsayılan Davranış
  40. Bölüm 8 — Konu 41: `assert` ile Geliştirme Zamanı Kontrolleri
  41. Bölüm 9 — Konu 42: Generic Sınıflar ve Fonksiyonlar
  42. Bölüm 9 — Konu 43: Generic Sınırlamalar (`<T extends ...>`)
  43. Bölüm 9 — Konu 44: Dart'ın Built-in Generic Koleksiyonları Nasıl Çalışır
  44. Bölüm 10 — Konu 45: `Future` Kavramı, `async`/`await`
  45. Bölüm 10 — Konu 46: `Future.then`, Hata Yönetimi (`catchError`)
  46. Bölüm 10 — Konu 47: `Stream` Temelleri, `async*`, `yield`
  47. Bölüm 10 — Konu 48: `StreamController`, Broadcast Stream
  48. Bölüm 11 — Konu 49: `map`, `where`, `reduce`, `fold`
  49. Bölüm 11 — Konu 50: `sort`, Custom Comparator ile Sıralama
  50. Bölüm 11 — Konu 51: Iterable Kavramı Derinlemesine (Lazy Evaluation)
  51. Bölüm 11 — Konu 52: Cascade Notasyonu (`..`)
  52. Bölüm 12 — Konu 53: `pubspec.yaml`, pub.dev'den Paket Ekleme
  53. Bölüm 12 — Konu 54: Kütüphane Oluşturma, `import`/`export`, `part`/`part of`
  54. Bölüm 12 — Konu 55: Dart'ta Test Yazımı (`test` Paketi, Unit Test Mantığı)
  55. Bölüm 12 — Konu 56: Extension Methods
  56. Bölüm 12 — Konu 57: Dart'ın Derleme Modelleri (JIT vs AOT) ve Bunun Flutter'a Etkisi
  57. Bölüm 13 — Konu 59: Dart 3 Pattern Matching — Records, Destructuring, Sealed Classes, Exhaustive Switch
  58. Bölüm 13 — Konu 60: `Never` Tipi, `covariant` ve Generic Variance Detayları
  59. Bölüm 13 — Konu 61: Event Loop Derinlemesine — Microtask Queue vs Event Queue
  60. Bölüm 13 — Konu 62: Memory Model & Performans — Garbage Collection, `const` Nesnelerin Bellek Avantajı
  61. Bölüm 13 — Konu 63: Isolate'ler Arası Mesajlaşmanın Maliyeti ve `compute()`'un İç İşleyişi
  62. Bölüm 13 — Konu 64: FFI (Foreign Function Interface) — C Koduna Erişim
  63. Bölüm 13 — Konu 65: Sunucu Tarafında Dart — `dart:io`, `shelf` Paketiyle Basit Bir Backend/CLI Aracı Yazma
  64. Bölüm 13 — Konu 66: Derleyici & Analiz Araçları — `dart analyze`, Custom Lint Kuralları, `build_runner` Mimarisi
Dizinin sayfası →
İçindekiler 10 başlık
  1. Set Nedir?
  2. Set Oluşturma
  3. Otomatik Tekrar Eleme (Deduplication)
  4. Eleman Ekleme ve Çıkarma
  5. Neden List Değil de Set İndeksle Erişilemiyor?
  6. Küme (Set) Matematik Operasyonları
  7. Arama ve Kontrol Metodları
  8. List mi Set mi? — Karar Verme
  9. 🎯 Bu Dersten Çıkarılması Gerekenler
  10. 📝 Ödevler

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

dart
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:

dart
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:

dart
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:

dart
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

dart
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?

dart
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:

dart
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ı

dart
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ümelerinde List.contains()'ten performans olarak daha avantajlıdır.
  • Boş bir Set oluştururken tip belirtmen gerekir (<String>{}), yoksa Dart bunu Map sanı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, union ve difference sonuçlarını sırayla yazdır ve yorumla.
  • [ ] Set ve List ile 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 derslerini intersection ile bul.

Sıradaki konu: Bölüm 4 — Konu 18: Map — Key-Value Yapılar