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); // TeslaVeri 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ş isetrue, dolu isefalsedöner.isNotEmpty: Liste dolu isetruedöner.
print("Boyut : ${otomobiller.length}"); // Boyut : 4
print("Boş mu? : ${otomobiller.isEmpty}"); // false
print("Dolu mu? : ${otomobiller.isNotEmpty}"); // true5. 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
containsmetodunda 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.