Map: HashMap, TreeMap, LinkedHashMap
Map, anahtar-değer (key-value) çiftlerini tutan bir yapı. Her anahtar benzersiz (unique), her anahtar bir değere karşılık gelir. Collection interface'ini implement etmez ama Collections Framework'ün en önemli parçalarından biri.
Bunu gerçek bir sözlük gibi düşün. Kelimeyi (key) ararsın, anlamını (value) bulursun. Her kelime bir kere var ama farklı kelimeler aynı anlama sahip olabilir. Map'te de her key bir kere var ama farklı key'ler aynı value'ya sahip olabilir.
Map Temelleri
Map<String, Integer> ages = new HashMap<>();
// Ekleme
ages.put("Ali", 25);
ages.put("Veli", 30);
ages.put("Ayşe", 28);
ages.put("Ali", 26); // Ali zaten var — value GÜNCELLENIR (25 → 26)
// Erişim
int age = ages.get("Ali"); // 26
Integer age2 = ages.get("Kemal"); // null — key yok
int age3 = ages.getOrDefault("Kemal", 0); // 0 — key yoksa default
// Sorgulama
ages.containsKey("Veli"); // true
ages.containsValue(30); // true
ages.size(); // 3
ages.isEmpty(); // false
// Silme
ages.remove("Veli"); // Veli silindi
ages.remove("Ali", 99); // Silinmez! Value eşleşmeli (26 ≠ 99)
ages.remove("Ali", 26); // Silindi — key VE value eşleşti⚠️ null dönüşü:
get()null döndüğünde iki anlam var: key yok VEYA key var ama value null. Ayrım yapmak içincontainsKey()kullan.
Map<String, String> map = new HashMap<>();
map.put("key1", null); // Value olarak null
map.get("key1"); // null — var ama value null
map.get("key2"); // null — key yok
map.containsKey("key1"); // true — var
map.containsKey("key2"); // false — yokMap Üzerinde Gezinme
Map'te gezinmenin birkaç yolu var:
Map<String, Integer> scores = Map.of("Ali", 90, "Veli", 85, "Ayşe", 95);
// 1. keySet — sadece key'ler
for (String name : scores.keySet()) {
System.out.println(name + " → " + scores.get(name));
}
// 2. values — sadece değerler
for (int score : scores.values()) {
System.out.println(score);
}
// 3. entrySet — key-value çiftleri (EN VERİMLİ)
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + " → " + entry.getValue());
}
// 4. forEach (Java 8+)
scores.forEach((name, score) ->
System.out.println(name + " → " + score)
);💡 İpucu: Hem key hem value lazımsa
entrySet()kullan.keySet()ile dolaşıp her seferindeget(key)çağırmak ekstra lookup demek.
HashMap İç Yapısı
HashMap, hash tablosu kullanır. Key'in hashCode() değerine göre bir "bucket"a (kova) yerleştirir.
Bucket[0] → null
Bucket[1] → [Ali:25] → [Kemal:30] (hash collision — linked list)
Bucket[2] → null
Bucket[3] → [Veli:28]
...Java 8+: Bir bucket'taki eleman sayısı 8'i geçerse, linked list kırmızı-siyah ağaca dönüşür (O(n) → O(log n)).
Performans:
| Operasyon | Ortalama | En kötü |
|---|---|---|
put | O(1) | O(n) |
get | O(1) | O(n) |
remove | O(1) | O(n) |
containsKey | O(1) | O(n) |
containsValue | O(n) | O(n) |
"En kötü" durum tüm key'lerin aynı bucket'a düşmesi (kötü hashCode).
HashMap ve null
Map<String, Integer> map = new HashMap<>();
// null KEY — HashMap'te BİR tane null key olabilir
map.put(null, 100);
System.out.println(map.get(null)); // 100
// null VALUE — istediğin kadar
map.put("Ali", null);
map.put("Veli", null);TreeMap: Sıralı Map
TreeMap, key'leri doğal sırada (natural ordering) veya Comparator'a göre sıralı tutar.
Map<String, Integer> sorted = new TreeMap<>();
sorted.put("Zeynep", 28);
sorted.put("Ali", 25);
sorted.put("Mehmet", 30);
System.out.println(sorted); // {Ali=25, Mehmet=30, Zeynep=28} — alfabetik
Map<Integer, String> numMap = new TreeMap<>();
numMap.put(3, "üç");
numMap.put(1, "bir");
numMap.put(2, "iki");
System.out.println(numMap); // {1=bir, 2=iki, 3=üç} — sayısal sıraTreeMap performansı: tüm operasyonlar O(log n). HashMap'ten yavaş ama sıralama garantisi var.
// TreeMap null key KABUL ETMEZ
Map<String, Integer> tree = new TreeMap<>();
// tree.put(null, 1); // NullPointerException!
// Ters sıralama
Map<String, Integer> reversed = new TreeMap<>(Comparator.reverseOrder());
reversed.put("Ali", 25);
reversed.put("Veli", 30);
System.out.println(reversed); // {Veli=30, Ali=25}LinkedHashMap: Ekleme Sırasını Koruyan Map
Map<String, Integer> linked = new LinkedHashMap<>();
linked.put("Üçüncü", 3);
linked.put("Birinci", 1);
linked.put("İkinci", 2);
System.out.println(linked); // {Üçüncü=3, Birinci=1, İkinci=2} — ekleme sırası
// Access-order mode (erişim sırasına göre)
Map<String, Integer> accessOrder = new LinkedHashMap<>(16, 0.75f, true);
accessOrder.put("A", 1);
accessOrder.put("B", 2);
accessOrder.put("C", 3);
accessOrder.get("A"); // A'ya erişildi → sona taşınır
System.out.println(accessOrder); // {B=2, C=3, A=1}Access-order mode, LRU cache implementasyonu için mükemmel.
Üç Map Karşılaştırması
| Özellik | HashMap | TreeMap | LinkedHashMap |
|---|---|---|---|
| Sıralama | Yok | Key'e göre sıralı | Ekleme sırası |
| put/get | O(1) | O(log n) | O(1) |
| null key | ✅ (1 tane) | ❌ | ✅ (1 tane) |
| null value | ✅ | ✅ | ✅ |
| Thread-safe | ❌ | ❌ | ❌ |
Java 8+ Map Method'ları
Java 8 ile Map'e çok güçlü method'lar eklendi:
Map<String, Integer> scores = new HashMap<>();
scores.put("Ali", 90);
scores.put("Veli", 85);
// putIfAbsent — yoksa ekle, varsa dokunma
scores.putIfAbsent("Ali", 100); // Ali var — değişmez (90 kalır)
scores.putIfAbsent("Ayşe", 88); // Ayşe yok — eklendi
// getOrDefault — yoksa default dön
int score = scores.getOrDefault("Kemal", 0); // 0
// replace — varsa değiştir
scores.replace("Ali", 95); // Ali varsa 95 yap
scores.replace("Ali", 95, 100); // Ali=95 ise 100 yap (koşullu)
// compute — key'e göre hesapla
scores.compute("Ali", (key, val) -> val + 10); // Ali: 95 → 105
// computeIfAbsent — yoksa hesapla ve ekle
scores.computeIfAbsent("Can", key -> key.length() * 10); // Can → 30
// computeIfPresent — varsa hesapla
scores.computeIfPresent("Ali", (key, val) -> val * 2); // Ali: 105 → 210
// merge — birleştir
scores.merge("Ali", 10, Integer::sum); // Ali varsa: mevcut + 10
scores.merge("Deniz", 50, Integer::sum); // Deniz yoksa: 50Yaygın Pattern: Sayma (Counting)
String text = "hello world hello java hello";
String[] words = text.split(" ");
// Eski yöntem
Map<String, Integer> counts = new HashMap<>();
for (String word : words) {
if (counts.containsKey(word)) {
counts.put(word, counts.get(word) + 1);
} else {
counts.put(word, 1);
}
}
// Java 8 — merge ile
Map<String, Integer> counts2 = new HashMap<>();
for (String word : words) {
counts2.merge(word, 1, Integer::sum);
}
// Java 8 — getOrDefault ile
Map<String, Integer> counts3 = new HashMap<>();
for (String word : words) {
counts3.put(word, counts3.getOrDefault(word, 0) + 1);
}
System.out.println(counts2); // {java=1, world=1, hello=3}Yaygın Pattern: Gruplama (Grouping)
List<String> names = List.of("Ali", "Ayşe", "Ahmet", "Veli", "Volkan");
// İlk harfe göre grupla
Map<Character, List<String>> grouped = new HashMap<>();
for (String name : names) {
char firstChar = name.charAt(0);
grouped.computeIfAbsent(firstChar, k -> new ArrayList<>()).add(name);
}
// {A=[Ali, Ayşe, Ahmet], V=[Veli, Volkan]}
// Stream ile daha temiz
Map<Character, List<String>> grouped2 = names.stream()
.collect(Collectors.groupingBy(name -> name.charAt(0)));Map.of() — Immutable Map (Java 9+)
// 10 çifte kadar
Map<String, Integer> map = Map.of(
"Ali", 25,
"Veli", 30,
"Ayşe", 28
);
// 10'dan fazla entry
Map<String, Integer> bigMap = Map.ofEntries(
Map.entry("Ali", 25),
Map.entry("Veli", 30),
Map.entry("Ayşe", 28),
Map.entry("Can", 22)
);
// Değiştirilemez
// map.put("Kemal", 35); // UnsupportedOperationException!
// Map.copyOf (Java 10+)
Map<String, Integer> copy = Map.copyOf(map);⚠️ Map.of() kuralları: Null key yasak, null value yasak, duplicate key yasak (IllegalArgumentException fırlar).
Map ve equals/hashCode
HashMap key'leri için hashCode/equals kuralları, HashSet ile aynı:
// Kendi sınıfını key olarak kullanacaksan
public class ProductId {
private final String category;
private final int number;
// Constructor...
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProductId)) return false;
ProductId that = (ProductId) o;
return number == that.number && category.equals(that.category);
}
@Override
public int hashCode() {
return Objects.hash(category, number);
}
}
Map<ProductId, String> products = new HashMap<>();
products.put(new ProductId("ELK", 1), "Laptop");
products.get(new ProductId("ELK", 1)); // "Laptop" — equals/hashCode doğru çalışıyorÖzet
Map anahtar-değer çiftleri tutar — her key unique, value tekrar edebilir
HashMap en hızlı (O(1)), sıra garantisi yok, 1 null key kabul eder
TreeMap key'lere göre sıralı (O(log n)), null key kabul etmez
LinkedHashMap ekleme sırasını korur, access-order mode ile LRU cache yapılabilir
Java 8+ method'ları (
merge,compute,putIfAbsent) kodu çok sadeleştirir — sayma ve gruplama pattern'larında kullanKey olarak kendi sınıfını kullanacaksan hashCode() ve equals() override etmek zorunlu
AI Asistan
Sorularını yanıtlamaya hazır