← Kursa Dön
📄 Text · 10 min

Array vs ArrayList Karşılaştırma

Giriş

Artık hem dizileri (array) hem de ArrayList'i biliyorsun. İkisi de "birden fazla elemanı bir arada tutmak" için kullanılıyor. Peki hangisini ne zaman kullanacaksın? Bu ders tam olarak bu soruyu yanıtlıyor.

Kısa cevap: çoğu durumda ArrayList kullan. Ama bazı senaryolarda array daha mantıklı. Neden ve ne zaman — bunu detaylıca göreceğiz.

Temel Farklar

1. Boyut

En büyük fark bu. Array sabit boyutlu, ArrayList dinamik.

// Array — boyut sabit
int[] dizi = new int[5];
// 6. eleman? Yeni dizi oluştur, kopyala... uğraş.

// ArrayList — boyut dinamik
ArrayList<Integer> liste = new ArrayList<>();
liste.add(1);
liste.add(2);
// 100 eleman daha ekle, sorun yok.

Eleman sayısını önceden biliyorsan ve değişmeyecekse → Array. Eleman sayısı değişecekse → ArrayList.

2. Tip Desteği

// Array — primitive tipler desteklenir
int[] intDizi = new int[10];          // doğrudan int
double[] doubleDizi = new double[5];  // doğrudan double

// ArrayList — sadece referans tipleri
ArrayList<Integer> intListe = new ArrayList<>();   // Integer (wrapper)
ArrayList<Double> doubleListe = new ArrayList<>();  // Double (wrapper)

Primitive tip dizileri bellekte çok daha verimlidir. int 4 byte yer kaplar. Integer ise en az 16 byte (nesne overhead'i yüzünden). 1 milyon elemanlı bir dizi düşün — fark devasa.

3. Sözdizimi (Syntax)

// Array
int[] dizi = new int[3];
dizi[0] = 10;
int deger = dizi[0];
int boyut = dizi.length;

// ArrayList
ArrayList<Integer> liste = new ArrayList<>();
liste.add(10);              // eleman ekleme (sona)
int deger = liste.get(0);  // eleman okuma
liste.set(0, 20);          // eleman güncelleme
int boyut = liste.size();  // boyut

Array sözdizimi daha kısa ve doğrudan. ArrayList'te her şey metot çağrısı.

4. Çok Boyutluluk

// Array — 2D, 3D kolayca
int[][] matris = new int[3][3];
matris[0][1] = 42;

// ArrayList — iç içe liste (daha karmaşık)
ArrayList<ArrayList<Integer>> matris2 = new ArrayList<>();
matris2.add(new ArrayList<>());
matris2.get(0).add(42);

2D yapılar için array çok daha doğal ve okunabilir.

Performans Karşılaştırması

Bunu bir spor araba vs SUV analojisi ile düşün. Array spor araba gibi — hızlı ama esnek değil. ArrayList SUV gibi — biraz daha yavaş ama her şeyi taşır.

Elemana Erişim (get)

İşlemArrayArrayList
dizi[i] vs liste.get(i)O(1)O(1)

İkisi de aynı hızda. ArrayList arka planda da array kullandığı için erişim süresi aynı.

Eleman Ekleme

İşlemArrayArrayList
Sona eklemeYok (sabit boyut)O(1) amortized
Araya eklemeManuel (O(n))O(n)

ArrayList sona ekleme konusunda çok hızlı. Ama araya ekleme her ikisinde de yavaş çünkü elemanları kaydırmak gerekiyor.

Eleman Silme

İşlemArrayArrayList
Sondan silmeYokO(1)
Aradan silmeManuel (O(n))O(n)

Bellek Kullanımı

// 1000 int — Array
int[] dizi = new int[1000];
// Yaklaşık 4000 byte (4 byte × 1000)

// 1000 Integer — ArrayList
ArrayList<Integer> liste = new ArrayList<>();
// Yaklaşık 20000+ byte (Integer nesneleri + referanslar + overhead)

Array yaklaşık 5 kat daha az bellek kullanır (primitive tipler için). Bu fark büyük veri setlerinde önemli olur.

💡 İpucu: Performans farkı küçük listelerde (birkaç yüz eleman) ihmal edilebilir. "Premature optimization is the root of all evil" — önce doğru çalışan kod yaz, sonra gerekirse optimize et.

ArrayList Arka Planda Nasıl Çalışır?

ArrayList aslında içinde bir Object[] dizisi tutar. Eleman eklediğinde:

  1. Dizide yer varsa → elemanı koy

  2. Dizi doluysa → 1.5 kat büyük yeni dizi oluştur → elemanları kopyala → yeni elemanı koy

ArrayList<Integer> liste = new ArrayList<>();  // iç dizi boyutu: 10 (varsayılan)

// 10 eleman ekle → iç dizi doldu
// 11. eleman → yeni dizi boyutu: 15 (10 * 1.5)
// 15 eleman ekle → iç dizi doldu
// 16. eleman → yeni dizi boyutu: 22 (15 * 1.5)

Bu büyüme işlemi (resize) maliyetli çünkü tüm elemanlar kopyalanıyor. Ama nadir olduğu için ortalamada (amortized) O(1).

Initial Capacity Belirtme

Eğer yaklaşık kaç eleman ekleyeceğini biliyorsan, baştan kapasite belirtebilirsin:

// 10000 eleman ekleyeceğini biliyorsan
ArrayList<Integer> liste = new ArrayList<>(10000);

Bu gereksiz resize işlemlerini önler.

Dönüşümler

Array → ArrayList

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

// Yol 1: Arrays.asList
ArrayList<String> liste = new ArrayList<>(Arrays.asList(dizi));

// Yol 2: Manuel
ArrayList<String> liste2 = new ArrayList<>();
for (String s : dizi) {
    liste2.add(s);
}

⚠️ Dikkat: Arrays.asList() tek başına sabit boyutlu bir liste döner. add() veya remove() çağırırsan UnsupportedOperationException alırsın. Bu yüzden new ArrayList<>(Arrays.asList(...)) ile sarmalıyoruz.

// Bu listeye eleman ekleyemezsin!
List<String> sabitListe = Arrays.asList("a", "b", "c");
sabitListe.add("d");  // UnsupportedOperationException!

// Buna ekleyebilirsin
ArrayList<String> dinamikListe = new ArrayList<>(Arrays.asList("a", "b", "c"));
dinamikListe.add("d");  // sorun yok

Primitive Array → ArrayList

Primitive dizileri direkt dönüştüremezsin:

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

// Bu ÇALIŞMAZ
// ArrayList<Integer> liste = new ArrayList<>(Arrays.asList(intDizi));

// Manuel dönüşüm gerekli
ArrayList<Integer> liste = new ArrayList<>();
for (int sayi : intDizi) {
    liste.add(sayi);  // auto-boxing ile int → Integer
}

ArrayList → Array

ArrayList<String> liste = new ArrayList<>(Arrays.asList("Elma", "Armut", "Portakal"));

// String dizisine dönüştür
String[] dizi = liste.toArray(new String[0]);

// veya
String[] dizi2 = liste.toArray(new String[liste.size()]);

toArray(new String[0]) kullanımı Java'nın önerdiği modern yaklaşım. JVM bunu optimize eder.

ArrayList → Primitive Array

ArrayList<Integer> liste = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

// Manuel dönüşüm
int[] dizi = new int[liste.size()];
for (int i = 0; i < liste.size(); i++) {
    dizi[i] = liste.get(i);  // auto-unboxing
}

Ne Zaman Array Kullan?

  1. Eleman sayısı sabit ve biliniyor — haftanın 7 günü, yılın 12 ayı

  2. Performans kritik — milyon elemanlı veri, oyun döngüsü

  3. Primitive tiplerint[], double[] gibi (bellek tasarrufu)

  4. Çok boyutlu yapılar — matrisler, grid'ler, oyun tahtaları

  5. Düşük seviye işlemler — byte dizileri, dosya okuma/yazma

// İyi array kullanımı
byte[] dosyaIcerigi = Files.readAllBytes(path);  // dosya okuma
int[][] sudoku = new int[9][9];                    // oyun tahtası
double[] sinyal = new double[44100];               // ses verisi (1 saniyelik)

Ne Zaman ArrayList Kullan?

  1. Eleman sayısı değişecek — kullanıcı listesi, sepet, log kaydı

  2. Sık ekleme/silme — dinamik koleksiyon

  3. Hazır metotlara ihtiyaç varcontains, indexOf, remove

  4. Genel amaçlı kullanım — çoğu iş mantığı

// İyi ArrayList kullanımı
ArrayList<String> sepet = new ArrayList<>();          // alışveriş sepeti
ArrayList<String> loglar = new ArrayList<>();          // log kayıtları
ArrayList<Integer> rastgeleSayilar = new ArrayList<>(); // bilinmeyen sayıda

Pratik Karar Rehberi

Kendine şu soruları sor:

1. Eleman sayısı değişecek mi?
   Evet → ArrayList
   Hayır → Array veya ArrayList (ikisi de olur)

2. Primitive tip mi?
   Evet + performans önemli → Array
   Evet + performans önemsiz → ArrayList (wrapper ile)
   Hayır → ArrayList

3. Çok boyutlu mu?
   Evet → Array (çok daha kolay)
   Hayır → ArrayList

4. Emin değil misin?
   → ArrayList (daha güvenli tercih)

💡 İpucu: Emin değilsen ArrayList kullan. Daha sonra performans sorunu çıkarsa Array'e geçmek kolaydır. Ama Array'den ArrayList'e geçmek daha zahmetli (tüm sözdizimini değiştirmen gerekir).

Pratik Örnek: İkisini Birlikte Kullanma

import java.util.ArrayList;
import java.util.Arrays;

public class NotSistemi {
    public static void main(String[] args) {
        // Dersler sabit → array
        String[] dersler = {"Matematik", "Fizik", "Kimya"};

        // Öğrenciler dinamik → ArrayList
        ArrayList<String> ogrenciler = new ArrayList<>();
        ogrenciler.add("Ali");
        ogrenciler.add("Ayse");

        // Notlar sabit boyut (3 ders) → array
        int[] aliNotlari = {85, 90, 78};
        int[] ayseNotlari = {92, 88, 95};

        // Her öğrenci için rapor
        System.out.println(ogrenciler.get(0) + ": " + Arrays.toString(aliNotlari));
        System.out.println(ogrenciler.get(1) + ": " + Arrays.toString(ayseNotlari));

        // Yeni öğrenci geldi (ArrayList olduğu için sorun yok)
        ogrenciler.add("Mehmet");
        System.out.println("Toplam öğrenci: " + ogrenciler.size());
    }
}

Bu örnekte dersler sabit olduğu için array, öğrenciler dinamik olduğu için ArrayList kullandık. Gerçek projelerde de böyle karma kullanım sık görülür.

List Arayüzü (Interface) — Bonus

İleride OOP konularına geldiğinde List arayüzünü göreceksin. Şimdilik şunu bil:

// ArrayList yerine List tipinde tanımlama (tercih edilen)
List<String> isimler = new ArrayList<>();

Bu şekilde tanımlama, ileride ArrayList yerine LinkedList kullanmak istediğinde sadece sağ tarafı değiştirmeni sağlar. "Program to an interface, not an implementation" prensibi. Şimdilik sadece gör, ileride detaylı işleyeceğiz.

Özet

  • Array: sabit boyut, primitive destekler, daha hızlı, daha az bellek, sözdizimi basit

  • ArrayList: dinamik boyut, sadece referans tipler, hazır metotlar (add, remove, contains), daha esnek

  • Çoğu durumda ArrayList tercih edilir — esneklik ve kolaylık kazandırır

  • Performans kritik ve eleman sayısı sabit ise Array tercih edilir

  • Dönüşümler: Arrays.asList() + new ArrayList<>() (array→list), toArray() (list→array)

  • Şüphede kalırsan ArrayList seç, gerekirse sonra optimize et