← Kursa Dön
📄 Text · 12 min

Collections Framework Genel Bakış

Programlama büyük ölçüde veri gruplarını yönetmek demek. Kullanıcı listesi, ürün kataloğu, sipariş kuyruğu, ayarlar sözlüğü... Hepsi "bir grup veriyi organize et, eriş, değiştir" probleminin farklı yüzleri. Java'nın Collections Framework'ü bu iş için tasarlanmış devasa bir araç kutusu.

Bunu bir mutfak gibi düşün. Array basit bir bıçak — işini görür ama sınırlı. Collections Framework ise tam donanımlı mutfak: bıçak seti, tencere takımı, mikser, fırın. Her iş için doğru araç var, yeter ki hangisini ne zaman kullanacağını bil.

Neden Array Yetmez?

Array'ler temel ama ciddi kısıtlamaları var:

// Array sorunları
int[] numbers = new int[5];    // Sabit boyut — sonradan büyütemezsin
numbers[5] = 10;                // ArrayIndexOutOfBoundsException

// "3" var mı? Manuel arat
boolean found = false;
for (int n : numbers) {
    if (n == 3) { found = true; break; }
}

// Ortadan eleman silmek? Kâbus.
// Sıralı eklemek? Kendin yaz.
// Duplicate kontrolü? Kendin yaz.

Collections Framework bunların hepsini hazır sunar: dinamik boyut, kolay arama, sıralama, filtreleme, thread-safety seçenekleri ve çok daha fazlası.

Hiyerarşi: Büyük Resim

Collections Framework birkaç temel interface üzerine kurulu:

                     Iterable<E>
                         |
                    Collection<E>
                   /      |       \
              List<E>   Set<E>   Queue<E>
               |          |        |
           ArrayList   HashSet   LinkedList (hem List hem Queue)
           LinkedList  TreeSet   PriorityQueue
           Vector      LinkedHashSet  ArrayDeque


              Map<K,V>  (Collection'dan BAĞIMSIZ)
               |
           HashMap
           TreeMap
           LinkedHashMap
           Hashtable

Dikkat: Map Collection interface'ini implement etmez. Ayrı bir hiyerarşi. Ama yine Collections Framework'ün parçası.

Dört Ana Yapı

YapıNe İşe YararAnaloji
ListSıralı, index'li, duplicate'e izin verirAlışveriş listesi
SetSırasız, unique elemanlarÖğrenci numaraları kümesi
QueueFIFO sırası (kuyruk)Banka kuyruğu
MapAnahtar-değer çiftleriSözlük (kelime→anlam)
// List — sıralı, tekrar olabilir
List<String> names = new ArrayList<>();
names.add("Ali");
names.add("Veli");
names.add("Ali"); // Tekrar OK
System.out.println(names.get(0)); // "Ali" — index ile erişim

// Set — tekrar yok
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Ali");
uniqueNames.add("Veli");
uniqueNames.add("Ali"); // Eklenmez, zaten var
System.out.println(uniqueNames.size()); // 2

// Queue — kuyruk mantığı
Queue<String> queue = new LinkedList<>();
queue.offer("Müşteri 1");
queue.offer("Müşteri 2");
System.out.println(queue.poll()); // "Müşteri 1" — ilk giren ilk çıkar

// Map — anahtar-değer
Map<String, Integer> ages = new HashMap<>();
ages.put("Ali", 25);
ages.put("Veli", 30);
System.out.println(ages.get("Ali")); // 25

Collection Interface: Ortak Method'lar

List, Set ve Queue'nun ortak atası Collection interface'idir. Temel method'lar:

Collection<String> col = new ArrayList<>();

// Ekleme
col.add("Java");              // Eleman ekle
col.addAll(List.of("Python", "Go")); // Toplu ekle

// Sorgulama
col.size();                    // Eleman sayısı
col.isEmpty();                 // Boş mu?
col.contains("Java");         // İçeriyor mu?
col.containsAll(List.of("Java", "Go")); // Hepsini içeriyor mu?

// Silme
col.remove("Python");         // Tek eleman sil
col.removeAll(List.of("Go")); // Toplu sil
col.retainAll(List.of("Java")); // Sadece bunları tut, kalanı sil
col.clear();                   // Hepsini sil

// Dönüşüm
Object[] arr = col.toArray();           // Object dizisine
String[] strArr = col.toArray(new String[0]); // Tipli diziye

Iterator Pattern

Collection'lar üzerinde gezinmenin standart yolu Iterator'dır. for-each döngüsü aslında arka planda Iterator kullanır.

List<String> fruits = new ArrayList<>(List.of("Elma", "Armut", "Muz"));

// Yol 1: for-each (en yaygın)
for (String fruit : fruits) {
    System.out.println(fruit);
}

// Yol 2: Iterator (silme yapacaksan bunu kullan)
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
    String fruit = it.next();
    if (fruit.equals("Armut")) {
        it.remove(); // Güvenli silme — ConcurrentModificationException olmaz
    }
}

// Yol 3: forEach method (Java 8+)
fruits.forEach(fruit -> System.out.println(fruit));
fruits.forEach(System.out::println); // Method reference

⚠️ Dikkat: for-each döngüsü içinde koleksiyondan eleman silersen ConcurrentModificationException alırsın. Silme yapacaksan Iterator kullan.

// YANLIŞ — ConcurrentModificationException
for (String fruit : fruits) {
    if (fruit.equals("Armut")) {
        fruits.remove(fruit); // BOOM!
    }
}

// DOĞRU — Iterator.remove()
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
    if (it.next().equals("Armut")) {
        it.remove(); // Güvenli
    }
}

// DOĞRU — removeIf (Java 8+)
fruits.removeIf(fruit -> fruit.equals("Armut"));

ListIterator

List için özel bir iterator. İleri-geri gidebilir, index bilgisine erişebilir, eleman ekleyip değiştirebilir:

List<String> colors = new ArrayList<>(List.of("Kırmızı", "Yeşil", "Mavi"));
ListIterator<String> lit = colors.listIterator();

while (lit.hasNext()) {
    int index = lit.nextIndex();
    String color = lit.next();
    System.out.println(index + ": " + color);
    
    if (color.equals("Yeşil")) {
        lit.set("Sarı");      // Yeşil → Sarı
        lit.add("Turuncu");    // Sarı'dan sonra Turuncu ekle
    }
}
// Sonuç: [Kırmızı, Sarı, Turuncu, Mavi]

Collections Utility Class

java.util.Collections sınıfı (büyük C, sonunda s) statik utility method'lar içerir. Collection interface'i ile karıştırma.

List<Integer> nums = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9));

// Sıralama
Collections.sort(nums);                    // [1, 1, 3, 4, 5, 9]
Collections.sort(nums, Comparator.reverseOrder()); // [9, 5, 4, 3, 1, 1]

// Karıştırma
Collections.shuffle(nums);                // Rastgele sıra

// Min/Max
int min = Collections.min(nums);          // En küçük
int max = Collections.max(nums);          // En büyük

// Ters çevir
Collections.reverse(nums);               // Sırayı ters çevir

// Arama (sıralı listede)
Collections.sort(nums);
int index = Collections.binarySearch(nums, 4); // Binary search

// Doldur
Collections.fill(nums, 0);               // Hepsini 0 yap

// Frekans
List<String> words = List.of("a", "b", "a", "c", "a");
int freq = Collections.frequency(words, "a"); // 3

Unmodifiable ve Immutable Collections

Değiştirilemez koleksiyonlar oluşturmanın birkaç yolu:

// Collections.unmodifiableXxx — sarmalayıcı (wrapper)
List<String> original = new ArrayList<>(List.of("A", "B"));
List<String> unmod = Collections.unmodifiableList(original);
// unmod.add("C"); // UnsupportedOperationException!
original.add("C"); // AMA orijinal hâlâ değiştirilebilir! unmod da değişir.

// List.of / Set.of / Map.of (Java 9+) — gerçek immutable
List<String> immutable = List.of("A", "B", "C");
// immutable.add("D"); // UnsupportedOperationException!
// Orijinal yok, gerçekten değiştirilemez

// List.copyOf (Java 10+) — kopyalayarak immutable
List<String> copy = List.copyOf(original);
original.add("D"); // copy ETKİLENMEZ

💡 İpucu: List.of(), Set.of(), Map.of() null eleman kabul etmez. List.of(null) → NullPointerException. Eski Arrays.asList() ise null'a izin verir.

// Factory method'lar (Java 9+)
List<String> list = List.of("A", "B", "C");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("Ali", 25, "Veli", 30);

// 10'dan fazla entry için Map.ofEntries
Map<String, Integer> bigMap = Map.ofEntries(
    Map.entry("Ali", 25),
    Map.entry("Veli", 30),
    Map.entry("Ayşe", 28)
);

Synchronized Wrappers

Normal Collection'lar thread-safe değildir. Multi-thread ortamda kullanacaksan:

// Synchronized wrapper
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());

// AMA iterasyon sırasında hâlâ manuel senkronizasyon gerekir
synchronized (syncList) {
    for (String item : syncList) {
        System.out.println(item);
    }
}

Modern alternatif: java.util.concurrent paketi — ConcurrentHashMap, CopyOnWriteArrayList gibi. Bunları ileride göreceğiz.

Generics ve Collections

Collections Framework generics ile birlikte çalışır. Tip güvenliği sağlar:

// Generic olmadan (Java 5 öncesi) — TEHLİKELİ
List list = new ArrayList();
list.add("text");
list.add(42);
String s = (String) list.get(1); // ClassCastException! Runtime'da patlar.

// Generic ile — GÜVENLİ
List<String> list = new ArrayList<>();
list.add("text");
// list.add(42); // Compile error — int ekleyemezsin
String s = list.get(0); // Cast gerekmez

Diamond operator (<>) ile sağ tarafta tipi tekrar yazmana gerek yok:

// Java 7+
Map<String, List<Integer>> map = new HashMap<>(); // Sağ taraf boş <>

Doğru Koleksiyonu Seçmek

İhtiyaçKullan
Sıralı erişim, index ileArrayList
Çok fazla ekleme/silme (ortadan)LinkedList
Unique elemanlarHashSet
Unique + sıralıTreeSet
Key-value eşlemeHashMap
Key-value + sıralı keyTreeMap
FIFO kuyrukArrayDeque veya LinkedList
Öncelikli kuyrukPriorityQueue

💡 İpucu: Şüpheye düştüğünde ArrayList ve HashMap ile başla. Çoğu durumda en iyi performansı verirler. Spesifik bir ihtiyaç çıkarsa değiştir.

Interface'e Programla

Değişken tipini interface olarak tanımla, implementasyonu sonra belirle. Bu esneklik sağlar:

// İYİ — interface tipinde
List<String> names = new ArrayList<>();
Set<Integer> ids = new HashSet<>();
Map<String, Object> config = new HashMap<>();

// KÖTÜ — implementasyon tipinde
ArrayList<String> names = new ArrayList<>();
HashSet<Integer> ids = new HashSet<>();

Neden? İleride ArrayList'i LinkedList'e, HashSet'i TreeSet'e değiştirmek istersen, sadece sağ tarafı değiştirirsin. Sol taraf List, Set olarak kaldığı için kullanan kodların hiçbiri etkilenmez.

Özet

  • Collections Framework, array'in sınırlamalarını aşan dinamik, esnek veri yapıları sunar

  • Dört ana yapı: List (sıralı, indexli), Set (unique), Queue (FIFO), Map (key-value)

  • Iterator koleksiyonda güvenli gezinme sağlar — silme yapacaksan Iterator.remove() veya removeIf() kullan

  • Collections (büyük C) utility class'ı: sort, shuffle, min/max, unmodifiable wrappers

  • List.of(), Set.of(), Map.of() (Java 9+) ile immutable koleksiyonlar oluştur

  • Değişkenleri interface tipinde tanımla (List, Set, Map) — implementasyona bağlanma