Legacy Collections
Java'nın tarihi uzun. Collections Framework Java 1.2'de (1998) geldi ama ondan önce de bazı koleksiyon sınıfları vardı: Vector, Hashtable, Stack. Framework gelince bunlar "geriye uyumluluk" için tutuldu ama artık kullanılmamalı.
Bu konuyu öğrenmek önemli çünkü eski kodlarda (legacy systems), iş görüşme sorularında ve Java sertifika sınavlarında karşına çıkar. Ama yeni kod yazarken bunlardan uzak dur.
Analoji: Vector ve Hashtable, Nokia 3310 gibi. Zamanında harika, hâlâ çalışıyor, ama bugün akıllı telefon varken onu cebine koymak mantıksız.
Vector vs ArrayList
Vector, ArrayList'in eski versiyonu. İkisi de dinamik dizi kullanır. Temel fark: Vector'ın tüm method'ları synchronized.
// Vector — eski
Vector<String> vector = new Vector<>();
vector.add("Ali");
vector.add("Veli");
vector.get(0); // "Ali"
// ArrayList — modern
List<String> list = new ArrayList<>();
list.add("Ali");
list.add("Veli");
list.get(0); // "Ali"API neredeyse aynı. Peki fark ne?
| Özellik | Vector | ArrayList |
|---|---|---|
| Synchronized | ✅ Her method | ❌ |
| Büyüme | 2 katına çıkar | 1.5 katına çıkar |
| Performans | Yavaş (lock overhead) | Hızlı |
| Thread-safe | ✅ (ama yetersiz) | ❌ |
| Java sürümü | 1.0 | 1.2 |
Vector neden kötü:
Gereksiz senkronizasyon. Çoğu kod tek thread'de çalışır. Her method çağrısında lock almak tamamen gereksiz overhead.
Yetersiz senkronizasyon. Paradoks gibi görünüyor ama doğru. Method bazlı senkronizasyon, birleşik operasyonları korumaz:
// THREAD-SAFE DEĞİL — iki ayrı synchronized çağrı arası koruma yok
Vector<String> v = new Vector<>();
if (!v.contains("Ali")) { // synchronized
v.add("Ali"); // synchronized — ama arası korumasız!
}
// Başka bir thread tam arada "Ali" ekleyebilir → duplicateModern alternatifler çok daha iyi:
// Tek thread → ArrayList
List<String> list = new ArrayList<>();
// Multi-thread → CopyOnWriteArrayList veya synchronized wrapper
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
List<String> cowList = new CopyOnWriteArrayList<>();
// Daha iyi → java.util.concurrent paketindeki yapılarHashtable vs HashMap
Aynı hikaye, farklı karakterler. Hashtable, HashMap'in eski, synchronized versiyonu.
// Hashtable — eski
Hashtable<String, Integer> table = new Hashtable<>();
table.put("Ali", 25);
table.get("Ali"); // 25
// HashMap — modern
Map<String, Integer> map = new HashMap<>();
map.put("Ali", 25);
map.get("Ali"); // 25| Özellik | Hashtable | HashMap |
|---|---|---|
| Synchronized | ✅ Her method | ❌ |
| null key | ❌ | ✅ (1 tane) |
| null value | ❌ | ✅ |
| Performans | Yavaş | Hızlı |
| Java sürümü | 1.0 | 1.2 |
| Fail-fast iterator | ❌ (Enumerator) | ✅ |
// Hashtable null kabul etmez
Hashtable<String, String> ht = new Hashtable<>();
// ht.put(null, "value"); // NullPointerException!
// ht.put("key", null); // NullPointerException!
// HashMap null kabul eder
HashMap<String, String> hm = new HashMap<>();
hm.put(null, "value"); // OK
hm.put("key", null); // OKModern alternatifler:
// Tek thread → HashMap
Map<String, Integer> map = new HashMap<>();
// Multi-thread → ConcurrentHashMap (EN İYİSİ)
Map<String, Integer> concMap = new ConcurrentHashMap<>();
// Synchronized wrapper (daha az tercih)
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());💡 İpucu:
ConcurrentHashMap, Hashtable'dan çok daha iyi thread-safety sağlar. Tüm map'i kilitlemek yerine, segment bazlı kilit kullanır (Java 8+'da bin/node bazlı). Concurrent erişim çok daha hızlı.
Stack Sınıfı
Stack, Vector'dan türer. LIFO (Last-In, First-Out) yapısı. Ama Vector'dan miras aldığı tüm sorunları taşır + daha fazlasını.
// Stack — ESKİ
Stack<String> stack = new Stack<>();
stack.push("A");
stack.push("B");
stack.push("C");
stack.pop(); // "C"
stack.peek(); // "B"
// Sorun: Vector'dan gelen method'lar Stack mantığını bozar
stack.add(0, "X"); // Ortaya eleman ekleyebilirsin — Stack gibi değil!
stack.remove(1); // Index ile silebilirsin — Stack gibi değil!
stack.get(0); // Random access — Stack gibi değil!Stack'in en büyük sorunu: Vector'dan extend etmesi (IS-A ilişkisi). Stack bir Vector değildir — composition (HAS-A) kullanmalıydı. Bu tasarım hatası Stack'i bozuk bir soyutlama yapıyor.
// DOĞRU YOL — Deque kullan
Deque<String> stack = new ArrayDeque<>();
stack.push("A");
stack.push("B");
stack.push("C");
stack.pop(); // "C"
stack.peek(); // "B"
// Random access YOK — gerçek stack davranışıEnumeration vs Iterator
Eski koleksiyonlar Enumeration kullanır, yeni koleksiyonlar Iterator:
// Enumeration — eski
Vector<String> v = new Vector<>(List.of("A", "B", "C"));
Enumeration<String> en = v.elements();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
// Iterator — modern
List<String> list = new ArrayList<>(List.of("A", "B", "C"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}| Özellik | Enumeration | Iterator |
|---|---|---|
| remove() desteği | ❌ | ✅ |
| Fail-fast | ❌ | ✅ |
| Method isimleri | Uzun (hasMoreElements) | Kısa (hasNext) |
| forEachRemaining | ❌ | ✅ (Java 8+) |
Synchronized Wrappers
Collections Framework, herhangi bir koleksiyonu synchronized yapabilen wrapper method'lar sunar:
// Synchronized wrappers
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
SortedSet<Integer> syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>());
SortedMap<String, Integer> syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>());Ama aynı sorun var — birleşik operasyonlar korunmaz:
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// BU THREAD-SAFE DEĞİL!
if (!syncList.contains("Ali")) {
syncList.add("Ali");
}
// İterasyon da manuel senkronize edilmeli
synchronized (syncList) {
for (String item : syncList) {
System.out.println(item);
}
}⚠️ Tercih sırası: 1. Tek thread → Normal koleksiyon (ArrayList, HashMap) 2. Multi-thread, çok okuma, az yazma → CopyOnWriteArrayList 3. Multi-thread, çok yazma → ConcurrentHashMap, ConcurrentLinkedQueue 4. Synchronized wrapper → Son çare
Properties Sınıfı
Properties, Hashtable<Object,Object>'dan türer. Yapılandırma dosyaları (.properties) okumak için kullanılır. Legacy bir sınıf ama hâlâ yaygın.
// properties dosyası oluştur/oku
Properties props = new Properties();
props.setProperty("db.host", "localhost");
props.setProperty("db.port", "5432");
String host = props.getProperty("db.host"); // "localhost"
String timeout = props.getProperty("timeout", "30"); // Default: "30"
// Dosyadan oku
try (FileInputStream fis = new FileInputStream("config.properties")) {
props.load(fis);
}
// Dosyaya yaz
try (FileOutputStream fos = new FileOutputStream("config.properties")) {
props.store(fos, "Uygulama ayarları");
}Properties hâlâ kullanılır ama modern projelerde YAML, JSON veya framework bazlı konfigürasyon tercih edilir.
Neden Legacy Koleksiyonları Kullanmamalısın — Özet Tablo
| Eski | Yeni | Neden |
|---|---|---|
Vector | ArrayList | Gereksiz sync overhead |
Hashtable | HashMap | Gereksiz sync, null kısıtlaması |
Stack | ArrayDeque | Bozuk abstraction (Vector IS-A) |
Enumeration | Iterator | remove() yok, fail-fast yok |
Dictionary (abstract) | Map | Tamamen obsolete |
Eski Kodu Modernleştirme
// ESKİ
Vector<String> names = new Vector<>();
Hashtable<String, Integer> ages = new Hashtable<>();
Stack<Integer> stack = new Stack<>();
Enumeration<String> en = names.elements();
while (en.hasMoreElements()) {
String name = en.nextElement();
}
// YENİ
List<String> names = new ArrayList<>();
Map<String, Integer> ages = new HashMap<>();
Deque<Integer> stack = new ArrayDeque<>();
for (String name : names) {
// veya names.forEach(...)
}Özet
Vector = synchronized ArrayList → gereksiz overhead, yerine
ArrayListkullanHashtable = synchronized HashMap → null kabul etmez, yerine
HashMapveyaConcurrentHashMapkullanStack = Vector'dan extend eden LIFO → bozuk soyutlama, yerine
ArrayDequekullanEnumeration = eski Iterator → remove() yok, fail-fast yok, yerine
IteratorkullanLegacy koleksiyonların "thread-safe" olması yanıltıcı — method bazlı sync, birleşik operasyonları korumaz
Multi-thread ihtiyacı için
java.util.concurrentpaketini kullan (ConcurrentHashMap,CopyOnWriteArrayList)
AI Asistan
Sorularını yanıtlamaya hazır