← Kursa Dön
📄 Text · 15 min

Tek Boyutlu Diziler

Giriş

Şimdiye kadar değişkenlerle çalıştık. Bir tane int sayi = 5; dedik, bir tane değer tuttuk. Peki ya 100 öğrencinin notunu saklamak istersen? 100 tane değişken mi tanımlayacaksın? not1, not2, not3... Hayır, tabii ki hayır.

İşte tam burada diziler (arrays) devreye giriyor. Dizi, aynı türden birden fazla değeri tek bir isim altında saklayan veri yapısıdır. Bir dizi tanımladığında, bellekte yan yana kutucuklar açılır ve her kutucuğa bir numara (indeks) verilir.

Dizi Nedir?

Diziyi bir apartman gibi düşün. Apartmanın adı var (dizinin adı), her dairenin numarası var (indeks), ve her dairede bir kişi oturuyor (değer). 3 numaralı daireye gitmek istiyorsan, apartmanın adını ve daire numarasını bilmen yeterli.

Java'da diziler:

  • Sabit boyutludur — oluşturduktan sonra büyütemez veya küçültemezsin

  • Aynı türden elemanlar tutar — int dizisi sadece int tutar

  • Sıfırdan indekslenir — ilk eleman 0. indekste, ikinci eleman 1. indekste

Bu üç özellik dizilerin en temel kurallarıdır. Şimdi nasıl tanımlanır, bakalım.

Dizi Tanımlama

Java'da dizi tanımlamanın birkaç yolu var. Hepsini görelim.

Yol 1: Önce Tanımla, Sonra Oluştur

int[] notlar;           // dizi değişkeni tanımlandı (henüz bellekte yer yok)
notlar = new int[5];    // 5 elemanlık yer açıldı bellekte

Burada new int[5] dediğinde, bellekte 5 tane int kutucuk açılıyor. Hepsi varsayılan değerle (0) doluyor.

Yol 2: Tek Satırda Tanımla ve Oluştur

int[] notlar = new int[5];    // en yaygın kullanım
String[] isimler = new String[10];
double[] fiyatlar = new double[100];

Yol 3: Değerlerle Birlikte Oluştur

int[] notlar = {90, 85, 72, 95, 60};
String[] gunler = {"Pazartesi", "Sali", "Carsamba"};

Bu yöntemde boyutu sen belirtmiyorsun — Java eleman sayısına bakarak kendisi hesaplıyor.

Yol 4: new ile Değer Vererek

int[] notlar = new int[]{90, 85, 72, 95, 60};

Bu yöntem özellikle metoda parametre olarak dizi geçerken işe yarar.

💡 İpucu: Günlük kullanımda Yol 2 (boş dizi) ve Yol 3 (değerli dizi) en çok karşına çıkacak olanlar. Diğerlerini bilmen yeterli, ezberlemene gerek yok.

Varsayılan Değerler

new ile dizi oluşturduğunda, Java tüm elemanları varsayılan değerlerle doldurur:

TürVarsayılan Değer
int, short, byte, long0
float, double0.0
booleanfalse
char'\u0000' (boş karakter)
Referans tipleri (String, vs.)null
int[] sayilar = new int[3];
System.out.println(sayilar[0]); // 0
System.out.println(sayilar[1]); // 0
System.out.println(sayilar[2]); // 0

String[] isimler = new String[2];
System.out.println(isimler[0]); // null

Bu varsayılan değerler önemli. Özellikle String dizilerinde null kontrolü yapmayı unutma, yoksa NullPointerException alırsın.

Elemanlara Erişim ve Değer Atama

Dizinin elemanlarına indeks ile erişirsin. İndeksler 0'dan başlar.

int[] notlar = new int[5];

// Değer atama
notlar[0] = 90;
notlar[1] = 85;
notlar[2] = 72;
notlar[3] = 95;
notlar[4] = 60;

// Değer okuma
System.out.println("İlk not: " + notlar[0]);    // 90
System.out.println("Son not: " + notlar[4]);     // 60

// Değer güncelleme
notlar[2] = 78;  // 72 yerine 78 oldu

5 elemanlı bir dizide geçerli indeksler: 0, 1, 2, 3, 4. Yani son indeks = boyut - 1.

length Özelliği

Her dizinin bir length özelliği vardır. Dizideki eleman sayısını verir.

int[] notlar = {90, 85, 72, 95, 60};
System.out.println("Eleman sayısı: " + notlar.length); // 5

// Son elemana erişim
System.out.println("Son not: " + notlar[notlar.length - 1]); // 60

⚠️ Dikkat: length bir metot değil, bir field'dır. Parantez kullanmıyorsun: notlar.length ✅ — notlar.length() ❌. String'te length() metot, dizide length field. Bu farkı unutma.

Dizi Üzerinde Gezinme

Dizinin tüm elemanlarını işlemek istediğinde döngü kullanırsın. İki temel yol var.

for Döngüsü ile Gezinme

int[] notlar = {90, 85, 72, 95, 60};

for (int i = 0; i < notlar.length; i++) {
    System.out.println("Not " + i + ": " + notlar[i]);
}

Bu klasik yöntem. İndeks numarasına ihtiyacın varsa (mesela "3. öğrenci" demek istiyorsan) bunu kullan.

for-each (Enhanced for) ile Gezinme

int[] notlar = {90, 85, 72, 95, 60};

for (int not : notlar) {
    System.out.println("Not: " + not);
}

for (int not : notlar) şunu diyor: "notlar dizisindeki her elemanı sırayla not değişkenine ata ve döngü gövdesini çalıştır."

for-each daha temiz ve okunabilir. Ama dezavantajı var: indeks numarasını bilmiyorsun ve elemanı değiştiremiyorsun.

int[] notlar = {90, 85, 72};

// Bu ÇALIŞMAZ — orijinal dizi değişmez
for (int not : notlar) {
    not = not + 10;  // sadece lokal kopya değişir
}

System.out.println(notlar[0]); // hâlâ 90

// Bunu yapman lazım
for (int i = 0; i < notlar.length; i++) {
    notlar[i] = notlar[i] + 10;  // orijinal dizi değişir
}

System.out.println(notlar[0]); // 100

💡 İpucu: Sadece okuma yapıyorsan → for-each. Elemanları değiştirmek veya indeks lazımsa → klasik for.

while ile Gezinme

Klasik for yerine while da kullanabilirsin, ama dizilerde pek tercih edilmez:

int[] sayilar = {10, 20, 30, 40};
int i = 0;

while (i < sayilar.length) {
    System.out.println(sayilar[i]);
    i++;
}

Sonuç aynı, ama for döngüsü bu iş için daha doğal ve okunabilir.

ArrayIndexOutOfBoundsException

Java'da dizilerle çalışırken en sık karşılaşacağın hata bu. Var olmayan bir indekse erişmeye çalıştığında Java sana bu hatayı fırlatır.

int[] notlar = {90, 85, 72};  // indeksler: 0, 1, 2

System.out.println(notlar[3]);  // HATA! 3. indeks yok
System.out.println(notlar[-1]); // HATA! Negatif indeks yok

Çıktı:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3

Bu hatanın en yaygın senaryoları:

int[] dizi = new int[5];

// Senaryo 1: <= yerine < kullanmayı unutmak
for (int i = 0; i <= dizi.length; i++) {  // HATA! i=5 olduğunda patlıyor
    System.out.println(dizi[i]);
}

// Doğrusu
for (int i = 0; i < dizi.length; i++) {   // i en fazla 4 olur
    System.out.println(dizi[i]);
}

// Senaryo 2: Boş dizi kontrolü yapmamak
int[] bos = new int[0];  // boş dizi (geçerli!)
System.out.println(bos[0]); // HATA! Eleman yok

⚠️ Dikkat: Döngülerde i <= dizi.length yazmak en klasik hatadır. Her zaman i < dizi.length kullan. Eşittir işareti seni yakacak.

Pratik Örnekler

Örnek 1: Dizinin Toplamı ve Ortalaması

int[] notlar = {90, 85, 72, 95, 60};
int toplam = 0;

for (int not : notlar) {
    toplam += not;
}

double ortalama = (double) toplam / notlar.length;
System.out.println("Toplam: " + toplam);       // 402
System.out.println("Ortalama: " + ortalama);   // 80.4

Burada (double) cast'ına dikkat et. Yoksa int / int sonucu yine int olur ve virgüllü kısım kaybolur.

Örnek 2: En Büyük ve En Küçük Eleman

int[] sayilar = {34, 12, 89, 5, 67, 43};

int enBuyuk = sayilar[0];
int enKucuk = sayilar[0];

for (int i = 1; i < sayilar.length; i++) {
    if (sayilar[i] > enBuyuk) {
        enBuyuk = sayilar[i];
    }
    if (sayilar[i] < enKucuk) {
        enKucuk = sayilar[i];
    }
}

System.out.println("En büyük: " + enBuyuk);  // 89
System.out.println("En küçük: " + enKucuk);  // 5

İlk elemanı başlangıç değeri olarak alıyoruz ve geri kalanlarla karşılaştırıyoruz. Integer.MIN_VALUE veya Integer.MAX_VALUE kullanmak da yaygın bir yaklaşım.

Örnek 3: Diziyi Ters Çevirme

int[] dizi = {1, 2, 3, 4, 5};

int baslangic = 0;
int bitis = dizi.length - 1;

while (baslangic < bitis) {
    // Swap (yer değiştir)
    int gecici = dizi[baslangic];
    dizi[baslangic] = dizi[bitis];
    dizi[bitis] = gecici;

    baslangic++;
    bitis--;
}

// Sonuç: {5, 4, 3, 2, 1}
for (int eleman : dizi) {
    System.out.print(eleman + " ");
}

İki uçtan başlayıp ortada buluşana kadar yer değiştiriyoruz. Bu "two pointer" tekniği algoritmalarda çok sık karşına çıkacak.

Dizileri Metotlara Geçirme

Diziler referans tipidir. Bir metoda dizi geçirdiğinde, kopyasını değil, orijinalini gönderiyorsun.

public static void main(String[] args) {
    int[] notlar = {50, 60, 70};
    hepsineEkle(notlar, 10);

    // Orijinal dizi değişti!
    for (int not : notlar) {
        System.out.print(not + " ");  // 60 70 80
    }
}

static void hepsineEkle(int[] dizi, int miktar) {
    for (int i = 0; i < dizi.length; i++) {
        dizi[i] += miktar;
    }
}

Bu davranışı anlamak çok önemli. Metoda int veya double gibi primitive geçirdiğinde kopya gider, orijinal değişmez. Ama dizi geçirdiğinde referans gider, orijinal değişir.

Metottan Dizi Döndürme

static int[] rastgeleDizi(int boyut) {
    int[] dizi = new int[boyut];
    for (int i = 0; i < boyut; i++) {
        dizi[i] = (int)(Math.random() * 100);
    }
    return dizi;
}

// Kullanım
int[] rastgele = rastgeleDizi(5);
for (int sayi : rastgele) {
    System.out.print(sayi + " ");
}

String Dizileri

String dizileri tam olarak int dizileri gibi çalışır, ama referans tipi oldukları için null olabilirler.

String[] meyveler = {"Elma", "Armut", "Portakal"};

for (String meyve : meyveler) {
    System.out.println(meyve + " (" + meyve.length() + " harf)");
}

Çıktı:

Elma (4 harf)
Armut (5 harf)
Portakal (8 harf)

null Kontrolü

String[] isimler = new String[3];
isimler[0] = "Ali";
// isimler[1] ve isimler[2] null

for (String isim : isimler) {
    if (isim != null) {
        System.out.println(isim.toUpperCase());
    } else {
        System.out.println("(boş)");
    }
}

null olan bir String üzerinde metot çağırırsan NullPointerException alırsın. Her zaman kontrol et.

Komut Satırı Argümanları (args)

main metodundaki String[] args aslında bir String dizisi! Programa dışarıdan veri göndermek için kullanılır.

public class Selamlama {
    public static void main(String[] args) {
        if (args.length > 0) {
            System.out.println("Merhaba, " + args[0] + "!");
        } else {
            System.out.println("Merhaba, dünya!");
        }
    }
}
$ java Selamlama Ali
Merhaba, Ali!

$ java Selamlama
Merhaba, dünya!

Her main metodunda gördüğün args artık sana yabancı değil — o sadece bir String dizisi.

Dizinin Kopyalanması

Dizi atamak kopya oluşturmaz! Sadece aynı diziye yeni bir referans ekler.

int[] orijinal = {1, 2, 3};
int[] kopya = orijinal;  // BU KOPYA DEĞİL!

kopya[0] = 99;
System.out.println(orijinal[0]); // 99 — orijinal de değişti!

Gerçek kopya yapmak için:

int[] orijinal = {1, 2, 3};

// Yol 1: Döngü ile
int[] kopya1 = new int[orijinal.length];
for (int i = 0; i < orijinal.length; i++) {
    kopya1[i] = orijinal[i];
}

// Yol 2: Arrays.copyOf (tercih edilen)
int[] kopya2 = Arrays.copyOf(orijinal, orijinal.length);

// Yol 3: clone
int[] kopya3 = orijinal.clone();

Arrays.copyOf kullanımını bir sonraki derste detaylı göreceğiz. Şimdilik "dizi atamak kopya yapmaz" kuralını aklına kazı.

Dizileri Yazdırma

Diziyi direkt println ile yazdırmaya çalışırsan sürprizle karşılaşırsın:

int[] notlar = {90, 85, 72};
System.out.println(notlar);  // [I@15db9742 — bu ne?!

Bu çıktı dizinin bellek adresini gösteriyor. İçeriğini görmek için:

import java.util.Arrays;

int[] notlar = {90, 85, 72};
System.out.println(Arrays.toString(notlar));  // [90, 85, 72]

Arrays.toString() dizinin içeriğini güzel formatlı bir String'e çevirir. Debug yaparken hayat kurtarır.

Yaygın Hatalar ve İpuçları

Hata 1: Dizi boyutunu değişken ile karıştırmak

int[] dizi = new int[5];
dizi[5] = 10;  // HATA! Son indeks 4

Hata 2: Diziyi başlatmadan kullanmak

int[] dizi;
dizi[0] = 5;  // HATA! dizi henüz oluşturulmadı (null)

Hata 3: for-each ile eleman değiştirmeye çalışmak

for (int x : dizi) {
    x = x * 2;  // orijinal dizi DEĞİŞMEZ
}

Hata 4: == ile dizi karşılaştırmak

int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a == b);              // false (referans karşılaştırır)
System.out.println(Arrays.equals(a, b)); // true (içerik karşılaştırır)

Özet

  • Dizi, aynı türden sabit sayıda elemanı bellekte yan yana tutan veri yapısıdır

  • İndeksler 0'dan başlar, son indeks length - 1'dir

  • for-each ile okuma, klasik for ile okuma + yazma yapılır

  • Var olmayan indekse erişim → ArrayIndexOutOfBoundsException

  • Dizi referans tipidir: metoda geçince orijinal değişir, = ile atamak kopya yapmaz

  • İçeriği yazdırmak için Arrays.toString(), karşılaştırmak için Arrays.equals() kullan