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
HashtableDikkat: Map Collection interface'ini implement etmez. Ayrı bir hiyerarşi. Ama yine Collections Framework'ün parçası.
Dört Ana Yapı
| Yapı | Ne İşe Yarar | Analoji |
|---|---|---|
| List | Sıralı, index'li, duplicate'e izin verir | Alışveriş listesi |
| Set | Sırasız, unique elemanlar | Öğrenci numaraları kümesi |
| Queue | FIFO sırası (kuyruk) | Banka kuyruğu |
| Map | Anahtar-değer çiftleri | Sö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")); // 25Collection 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 diziyeIterator 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
ConcurrentModificationExceptionalı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"); // 3Unmodifiable 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. EskiArrays.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 gerekmezDiamond 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 ile | ArrayList |
| Çok fazla ekleme/silme (ortadan) | LinkedList |
| Unique elemanlar | HashSet |
| Unique + sıralı | TreeSet |
| Key-value eşleme | HashMap |
| Key-value + sıralı key | TreeMap |
| FIFO kuyruk | ArrayDeque veya LinkedList |
| Öncelikli kuyruk | PriorityQueue |
💡 İpucu: Şüpheye düştüğünde
ArrayListveHashMapile 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()veyaremoveIf()kullanCollections (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
AI Asistan
Sorularını yanıtlamaya hazır