Yazılım geliştirme sürecinde verileri depolamak ve yönetmek için sadece dizileri veya listeleri (ArrayList, LinkedList vb.) kullanmak her zaman yeterli olmaz. Gündelik hayattan düşünelim: Bir sözlükte bir kelimenin anlamını ararken, kelimeleri baştan sona tek tek okumazsınız; doğrudan aradığınız kelimeye (anahtara) gider ve karşısındaki anlama (değere) ulaşırsınız. Veya bir telefon rehberinde isme karşılık gelen telefon numarasını ararsınız.
İşte Java’da bu “Anahtar-Değer” (Key-Value) mantığıyla çalışan veri yapılarına Map (Harita) adı verilir. Map’ler, verileri bir anahtar ve o anahtara bağlı bir değer olarak ikili gruplar halinde depolar. Java Collections Framework’ün (Koleksiyonlar Çatısı) en güçlü üyelerinden olan Map arayüzünün (interface) en popüler iki uygulaması ise HashMap ve TreeMap sınıflarıdır.
Bu kapsamlı rehberimizde, ilk defa öğrenecekler için Java’da HashMap ve TreeMap kavramlarını, nasıl çalıştıklarını ve aralarındaki farkları örneklerle adım adım inceleyeceğiz.
1. Map (Harita) Temel Kavramları Nelerdir?
Hem HashMap hem de TreeMap sınıflarını anlamadan önce, Map arayüzünün altın kurallarını bilmek gerekir:
- Benzersiz Anahtarlar (Unique Keys): Bir Map içinde aynı anahtardan (key) iki tane bulunamaz. Örneğin, bir telefon rehberinde “Ahmet” ismini anahtar yaparsanız, ikinci bir “Ahmet” eklediğinizde eski numaranın (değerin) üzerine yazılır.
- Çoklu Değerler (Duplicate Values): Anahtarlar benzersiz olmak zorundadır, ancak değerler (values) aynı olabilir. (Farklı iki kişinin telefon numarası veya adresi aynı olabilir).
- Iterable Değildir: Map’ler doğrudan
Iterablearayüzünü uygulamazlar. Yani bir Map’in üzerinde doğrudan standart birfor-eachdöngüsü kuramazsınız. Bunun yerine, Map’in içindeki anahtarlarıkeySet(), değerlerivalues()veya anahtar-değer ikililerinientrySet()metotları ile bir koleksiyon-görünümüne (collection-view) çevirerek döngüye sokarsınız.
2. Java’da HashMap Nedir ve Nasıl Çalışır?
HashMap, verileri arka planda bir “Hash Tablosu” (Hash Table) kullanarak depolayan bir Map türüdür. Java dünyasında en sık kullanılan veri yapılarından biridir.
Çalışma Mantığı: HashMap’e bir veri eklediğinizde (örneğin put("Elma", 50)), Java “Elma” anahtarının hashCode() metodunu çağırarak matematiksel ve benzersiz bir tam sayı (hash kodu) üretir. Bu kod, verinin hafızada hangi kutucuğa (indekse) konulacağını belirler. Eğer aradığınız bir veriyi getirmek isterseniz (get("Elma")), Java baştan sona arama yapmaz; anında “Elma” kelimesinin hash kodunu hesaplar ve doğrudan o hafıza adresine giderek değeri size teslim eder.
Bu muazzam mekanizma sayesinde, HashMap’in içine milyonlarca veri ekleseniz bile, bir veriyi ekleme (put) ve okuma (get) hızı neredeyse her zaman sabittir (O(1) zaman karmaşıklığı).
Önemli Bir Özellik: HashMap, içindeki elemanları sizin eklediğiniz sıraya veya alfabetik bir sıraya göre tutmaz. Arka plandaki hash kodlaması nedeniyle veriler tamamen rastgele (karmaşık) bir sırada depolanır.
HashMap Kullanım Örneği
Bir banka müşterisinin adını (String) ve hesap bakiyesini (Double) tutan basit bir HashMap örneği yapalım:
import java.util.HashMap;
import java.util.Map;
public class HashMapOrnegi {
public static void main(String[] args) {
// HashMap oluşturulması: <Anahtar Tipi, Değer Tipi>
HashMap<String, Double> bakiye = new HashMap<>();
// put() metodu ile veri ekleme
bakiye.put("Ahmet Yılmaz", 3450.50);
bakiye.put("Ayşe Demir", 1230.25);
bakiye.put("Mehmet Çelik", 99.99);
// get() metodu ile veri okuma
System.out.println("Ayşe'nin Bakiyesi: " + bakiye.get("Ayşe Demir")); // Çıktı: 1230.25
// Map üzerinde döngü kurmak için entrySet() kullanımı
for (Map.Entry<String, Double> musteri : bakiye.entrySet()) {
System.out.println("Müşteri: " + musteri.getKey() + " | Bakiye: " + musteri.getValue());
}
// Aynı anahtarla yeni veri eklersek, eski verinin üzerine yazar (Güncelleme yapar)
bakiye.put("Ahmet Yılmaz", 5000.00);
}
}
3. Java’da TreeMap Nedir ve Nasıl Çalışır?
TreeMap, verileri arka planda bir “Ağaç” (Red-Black Tree) yapısında saklayan bir Map türüdür.
Çalışma Mantığı: TreeMap, eklendiği anda anahtarları birbiriyle karşılaştırır ve onları artan sırada (ascending order) otomatik olarak sıralar. Eğer anahtarlar metin (String) ise A’dan Z’ye, sayı (Integer) ise küçükten büyüğe doğru yerleştirilir. Ağaç veri yapısının özelliği gereği, ekleme ve arama işlemleri HashMap kadar ışık hızında değildir; veriler eklendikçe ağaç dallanır ve arama hızı logaritmik zamana ($O(\log N)$) düşer.
Kendi belirlediğiniz özel bir sıralama mantığı (örneğin isme göre değil, ismin uzunluğuna göre sıralama) yapmak isterseniz, TreeMap’i oluştururken constructor (kurucu) içine kendi yazdığınız bir Comparator nesnesi verebilirsiniz.
TreeMap Kullanım Örneği
Yukarıdaki banka örneğini bu kez TreeMap ile yapalım:
import java.util.TreeMap;
import java.util.Map;
public class TreeMapOrnegi {
public static void main(String[] args) {
// TreeMap oluşturulması
TreeMap<String, Double> bakiye = new TreeMap<>();
// Veri ekleme
bakiye.put("John Doe", 3434.34);
bakiye.put("Tom Smith", 123.22);
bakiye.put("Jane Baker", 1378.00);
bakiye.put("Tod Hall", 99.22);
bakiye.put("Ralph Smith", -19.08);
// entrySet() ile verileri ekrana yazdırma
for (Map.Entry<String, Double> musteri : bakiye.entrySet()) {
System.out.println(musteri.getKey() + ": " + musteri.getValue());
}
}
}
Çıktıya Dikkat Edin: Siz verileri karışık sırayla eklemiş olsanız bile, program çalıştığında ekrana veriler alfabetik sıraya göre (Jane Baker, John Doe, Ralph Smith, Tod Hall, Tom Smith) yazdırılacaktır. TreeMap, verileri anında sıralamıştır.
4. HashMap ve TreeMap Arasındaki Temel Farklar
Yeni başlayan bir programcının mülakatlarda da sıkça karşılaşacağı bu iki veri yapısının temel farkları şunlardır:
| Özellik | HashMap | TreeMap |
|---|---|---|
| Arka Plan Yapısı | Hash Tablosu (Hash Table) kullanır. | Ağaç Yapısı (Red-Black Tree) kullanır. |
| Sıralama (Ordering) | Sırasızdır. Elemanların sırasını kesinlikle garanti etmez. | Sıralıdır. Anahtarları (key) her zaman küçükten büyüğe doğru sıralı tutar. |
| Performans ve Hız | Çok hızlıdır. get() ve put() işlemleri $O(1)$ sabit zaman alır. | Biraz daha yavaştır. Sıralama yaptığı için $O(\log N)$ zaman alır. |
| Null Anahtar İzni | Sadece 1 adet null anahtara izin verir. | null anahtara izin vermez. (Çünkü null ile başka bir kelimeyi kıyaslayıp sıralayamaz, NullPointerException fırlatır). |
| Karşılaştırma Yöntemi | Anahtarların eşitliğini kontrol etmek için hashCode() ve equals() metotlarını kullanır. | Sıralama ve eşitlik için compareTo() metodunu kullanır. |
Hangisini Ne Zaman Seçmelisiniz? (Stratejik İpucu)
Eğer yazılım projelerinizde sadece verileri bir anahtarla depolamak (örneğin T.C. Kimlik No -> Vatandaş Nesnesi eşleşmesi yapmak) ve bu verilere mümkün olan en hızlı şekilde erişmek istiyorsanız tartışmasız tercihiniz HashMap olmalıdır. Çoğu genel amaçlı senaryoda (işlerin %90’ında) Java geliştiricileri standart olarak HashMap kullanır.
Ancak;
- Müşterilerinizi isimlerine göre A’dan Z’ye sıralı bir şekilde listelemeniz gerekiyorsa,
- Bir puan tablosu (leaderboard) oluşturuyorsanız,
- Sadece belirli bir aralıktaki (örneğin baş harfi M ile N arasında olan) kişileri listeleyeceğiniz zengin alt harita (subMap) sorgulamaları yapacaksanız,
O zaman bu sıralama işlemlerini sizin yerinize otomatik ve hatasız yapan TreeMap sınıfını kullanmalısınız.
Özetle; Veri hızı ve performans için HashMap’i, verilerinizde “düzen ve sıralama” şart olduğunda ise TreeMap’i tercih etmelisiniz! Bol bol kod yazıp, Map.Entry arayüzü ile döngüler kurarak bu sınıfların gücünü bilgisayarınızda test etmeyi unutmayın.





