Dart Listeleri (List) Nedir? Detaylı Anlatım ve Örnekler

Yazılım geliştirme süreçlerinde verileri düzenli bir şekilde tutmak ve yönetmek hayati önem taşır. Dart dilinde en sık başvurduğumuz koleksiyon yapılarından biri Listelerdir. Diğer programlama dillerindeki “Array” (Dizi) yapısına benzeyen Listeler, sıralı veri gruplarını yönetmemizi sağlar.

Bu yazıda dart dilinde listelerin nasıl oluşturulduğunu, veri manipülasyonunun (Veri ekleme, güncelleme, silme işlemlerini, Okuma, sıralama ve ters çevirme yöntemlerini) nasıl yapıldığını ve sık kullanılan liste metotlarını detaylıca inceleyeceğiz.


Dart Listelerinin Temel Özellikleri

Dart listeleriyle ilgili bilinmesi gereken temel noktalar şunlardır:

  • Listelerde kalıcı depolama yoktur (RAM üzerinde tutulur).
  • Elemanlar 0. indexten başlayarak, eklendikleri sıraya göre yerleştirilir.
  • Liste elemanları genellikle aynı veri türünden oluşur.
  • Liste tanımlanırken veri eklenebilir veya boş oluşturulup daha sonra doldurulabilir.
  • Benzer türdeki verileri (sadece Stringler veya sadece Sayılar gibi) tutmak için tasarlanır.

1. Liste Tanımlama ve Oluşturma

Dart dilinde listeleri iki temel şekilde tanımlayabiliriz: İçeriği dolu bir liste veya daha sonra doldurulmak üzere boş bir liste.

// 1. İçeriği baştan belli olan liste
var renkler = ["mavi", "kırmızı", "sarı"];

// 2. Türü belirtilmiş boş liste (Önerilen yöntem)
var otomobiller = <String>[];

print(renkler);     // [mavi, kırmızı, sarı]
print(otomobiller); // []

Tür Güvenliği (Type Safety): <String> ifadesi, bu listenin sadece metinsel ifadeler kabul edeceğini garanti eder.

2. Listeye Veri Ekleme (Add ve Insert)

Listeler dinamik yapılardır, yani boyutları sonradan değiştirilebilir.

add() Metodu

Listeye yeni bir eleman eklemek için kullanılır. Eklenen eleman her zaman listenin en sonuna yerleşir.

  // Veri ekleme
  otomobiller.add("Audi");   // i[0]
  otomobiller.add("Volvo");  // i[1]
  otomobiller.add("Tesla");  // i[2]
  print(otomobiller); // [Audi, Volvo, Tesla]

insert() Metodu

Eğer veriyi listenin sonuna değil de, belirlediğimiz özel bir sıraya eklemek istersek insert metodunu kullanırız.

// 1. index'e "Honda" ekleyelim, diğerleri kaysın
otomobiller.insert(1, "Honda");

print(otomobiller); // Çıktı: [Audi, Honda, Volvo, Tesla]

3. Veri Okuma ve Güncelleme

Listelerdeki verilere ulaşmak veya onları değiştirmek için köşeli parantez [] ve index numarasını kullanırız.

Veri Okuma

Tüm listeyi yazdırmak yerine sadece spesifik bir elemanı çekmek istersek:

print(otomobiller); // Tüm liste: [Audi, Honda, Volvo, Tesla]

String secilenArac = otomobiller[3]; 
print(secilenArac); // Tesla

Veri Güncelleme

Var olan bir veriyi değiştirmek için, ilgili indexe yeni bir değer ataması yaparız.

Bu işlemi listeAdi[indexDeğeri] = "Güncel Veri"; şeklinde yaparız.

// Güncelleme
  otomobiller[1] = "Chery";
  print(otomobiller); // [Audi, Chery, Tesla]

4. Liste Durum Kontrolleri (Boyut ve Boşluk)

Uygulama geliştirirken listenin dolu olup olmadığını veya kaç elemanı olduğunu sıkça kontrol etmemiz gerekir.

  • length: Listenin eleman sayısını (boyutunu) verir.
  • isEmpty: Liste boş ise true, dolu ise false döner.
  • isNotEmpty: Liste dolu ise true döner.
print("Boyut : ${otomobiller.length}"); // Boyut : 4

print("Boş mu? : ${otomobiller.isEmpty}");     // false
print("Dolu mu? : ${otomobiller.isNotEmpty}");  // true

5. Verileri Anlamlı Okuma

Kullanıcı arayüzünde listeleri gösterirken verileri ham haliyle ([a, b, c]) değil, işlenmiş haliyle sunarız. Bunun için döngüler kullanılır.


For-in Döngüsü (Pratik Yöntem)

Verileri tek tek ele almak için en temiz yöntemdir.

// for each kullanarak liste içerisindeki verileri okuma
  for(var otomobil in otomobiller) {
    print("Sonuç : $otomobil");
  }
  
  // Program Çıktısı
  /*
  Sonuç : Audi
	Sonuç : Honda
	Sonuç : Chery
	Sonuç : Tesla
  */

Standart For Döngüsü (Index Tabanlı)

Eğer verinin sıra numarasına (index) da ihtiyacınız varsa bu yöntemi kullanmalısınız.

	// index değeriyle yazdırma
  for (var i=0;  i <otomobiller.length; i++){
    print("$i. -> ${otomobiller[i]}");
  }
  
  // Program Çıktısı
  /*
  0. -> Audi
	1. -> Honda
	2. -> Chery
	3. -> Tesla
  */

6. Sıralama ve Ters Çevirme İşlemleri

Verilerin sunum şeklini değiştirmek için Dart bize hazır fonksiyonlar sunar.

reverse (Tersine Çevirme)

Listeyi sondan başa doğru sıralar. Bu işlem orijinal listeyi bozmaz, sadece o anlık ters çevrilmiş bir görünüm döndürür. Bu yüzden .toList() ile tekrar listeye çeviririz.

// Bir listeyi tersine çevirme
  var tersListe = otomobiller.reversed.toList();
  print(otomobiller); // [Audi, Honda, Chery, Tesla]
  print(tersListe);   // [Tesla, Chery, Honda, Audi]

sort (Sıralama)

Listeyi varsayılan olarak küçükten büyüğe (veya A’dan Z’ye) sıralar. Bu işlem orijinal listeyi değiştirir.

// liste içerisindeki verileri sıralama
  otomobiller.sort();
  print(otomobiller); // [Audi, Chery, Honda, Tesla]

7. Veri Silme İşlemleri

Listeden eleman çıkarmak için indeks numarasını kullanabilir veya listeyi tamamen temizleyebiliriz.

removeAt()

Belirtilen indexteki veriyi siler ve listeyi kaydırır.

// Listeden veri silme
  otomobiller.removeAt(2);
  print(otomobiller); // [Audi, Chery, Tesla]

clear()

Listeyi tamamen boşaltır ve eleman sayısını 0’a indirir.

// Listedeki tüm verileri silme - Listeyi sıfırlama
  otomobiller.clear();
  print(otomobiller); // []

Nesne Tabanlı Listeler: Sıralama (Sort) ve Filtreleme (Filter) İşlemleri

Gerçek hayat projelerinde (örneğin bir E-Ticaret uygulamasında ürünleri listelerken) listelerimiz sadece basit metinlerden (String) veya sayılardan (int) oluşmaz. Genellikle kendi oluşturduğumuz Sınıf (Class) yapılarından üretilen Nesneleri (Objects) listeleriz.

1. Sınıf Modellemesi ve Liste Oluşturma

Öncelikle üzerinde çalışacağımız veri modelini oluşturmalıyız. Örneğimizde plaka kodu ve şehir adını tutan bir Sehirler sınıfı tasarlıyoruz.

class Sehirler {
  int plaka;
  String sehirAdi;

  // Constructor (Kurucu Metot)
  Sehirler({required this.plaka, required this.sehirAdi});
}

Bu sınıftan nesneler üretip, bu nesneleri tutacak bir liste tanımlayalım.

void main() {
  // Nesnelerin oluşturulması
  var sehir1 = Sehirler(plaka: 41, sehirAdi: "Kocaeli");
  var sehir2 = Sehirler(plaka: 23, sehirAdi: "Elazığ");
  var sehir3 = Sehirler(plaka: 54, sehirAdi: "Sakarya");
  var sehir4 = Sehirler(plaka: 06, sehirAdi: "Ankara");

  // Nesne tabanlı listenin oluşturulması
  var sehirListesi = <Sehirler>[];

  // Nesnelerin listeye eklenmesi
  sehirListesi.add(sehir1);
  sehirListesi.add(sehir2);
  sehirListesi.add(sehir3);
  sehirListesi.add(sehir4);

  // Listeyi yazdırma
  for (var sehir in sehirListesi) {
    print("Plaka : ${sehir.plaka} - Şehir : ${sehir.sehirAdi}");
  }
}

2. Listelerde Sıralama (Sorting) İşlemleri

Basit listelerde sort() metodu verileri otomatik sıralıyordu. Ancak nesne tabanlı listelerde Dart dili, hangi alana göre (Plaka mı? Şehir adı mı?) sıralama yapacağını bilemez. Bu yüzden Comparator yapısını kullanırız.

compareTo fonksiyonu iki değeri karşılaştırır.

  • Küçükten Büyüğe (Ascending): x.compareTo(y)
  • Büyükten Küçüğe (Descending): y.compareTo(x)

Sayısal Sıralama (Plakaya Göre)

// 1. Küçükten Büyüğe Sıralama (Ascending)
  print("--- Sayısal : Küçükten Büyüğe ---");
  
  Comparator<Sehirler> plakaKucuktenBuyuge = (x, y) => x.plaka.compareTo(y.plaka);
  sehirListesi.sort(plakaKucuktenBuyuge);

  for(var sehir in sehirListesi){
    print("Plaka : ${sehir.plaka} - Şehir : ${sehir.sehirAdi}");
  }

  // 2. Büyükten Küçüğe Sıralama (Descending)
  print("--- Sayısal : Büyükten Küçüğe ---");
  
  Comparator<Sehirler> plakaBuyuktenKucuge = (x, y) => y.plaka.compareTo(x.plaka);
  sehirListesi.sort(plakaBuyuktenKucuge);
  
  // Listeyi tekrar yazdırırsanız sıranın değiştiğini göreceksiniz.

Metinsel Sıralama (Şehir Adına Göre)

Aynı mantık metinsel ifadeler için de geçerlidir. Alfabetik sıralama yapar.

// 3. İsim Sırasına Göre (A-Z)
  print("--- Metinsel : A'dan Z'ye ---");
  
  Comparator<Sehirler> isimSirala = (x, y) => x.sehirAdi.compareTo(y.sehirAdi);
  sehirListesi.sort(isimSirala);

  // 4. İsim Sırasının Tersi (Z-A)
  print("--- Metinsel : Z'den A'ya ---");
  
  Comparator<Sehirler> isimTersSirala = (x, y) => y.sehirAdi.compareTo(x.sehirAdi);
  sehirListesi.sort(isimTersSirala);

3. Listelerde Filtreleme (Filtering) İşlemleri

Bazen listedeki tüm verileri değil, sadece belirli şartları sağlayan verileri çekmek isteriz. Bunun için where metodu kullanılır.

Önemli Not: where metodu geriye doğrudan bir List döndürmez, Iterable (yinelenebilir) bir yapı döndürür. Bu yüzden işlem sonunda .toList() diyerek sonucu tekrar listeye çevirmemiz gerekir.

Sayısal Filtreleme

Örneğin: Plakası 20’den büyük VE 45’ten küçük olan şehirleri getirelim.

print("------------ Filtreleme : Plaka Aralığı ------------");
  
  Iterable<Sehirler> filtre1 = sehirListesi.where((sehirNesnesi){
    return sehirNesnesi.plaka > 20 && sehirNesnesi.plaka < 45;
  });

  var filtre1Liste = filtre1.toList(); // Iterable'ı Listeye çeviriyoruz
  
  for(var sehir in filtre1Liste){
    print("Plaka : ${sehir.plaka} - Şehir : ${sehir.sehirAdi}");
  }
  // Çıktı: Kocaeli (41), Elazığ (23) gibi aralıktaki iller olacaktır.

Metinsel Filtreleme

Örneğin: Şehir adı içerisinde “k” harfi geçen şehirleri bulalım. Bunun için contains metodunu kullanırız.

Önemli Not: Dart dilince contains metodunda büyük küçük harf duyarlılığı vardır.

print("------------ Filtreleme : İsmi 'k' içerenler ------------");
  
  Iterable<Sehirler> filtre2 = sehirListesi.where((sehirNesnesi){
    return sehirNesnesi.sehirAdi.contains("k"); // Büyük-küçük harf duyarlılığına dikkat edilmelidir
  });

  var filtre2Liste = filtre2.toList();
  
  for(var sehir in filtre2Liste){
    print("Plaka : ${sehir.plaka} - Şehir : ${sehir.sehirAdi}");
  }

Sonuç

Dart dilinde Listeler, verileri organize etmek ve yönetmek için en temel yapı taşlarından biridir. Mobil uygulama geliştirirken, API’den gelen verileri listelemekten, kullanıcı sepeti oluşturmaya kadar pek çok alanda bu yapıları ve yukarıdaki metotları sıkça kullanacaksınız.

Dart dilinde listeler, Nesne Tabanlı Programlama (OOP) ile birleştiğinde çok güçlü bir veri yönetim aracı haline gelir. Özellikle Comparator kullanarak sıralama ve where kullanarak filtreleme işlemleri, dinamik mobil uygulamaların (arama çubukları, ürün filtreleri vb.) temelini oluşturur.