Java

Java’da HashMap Nedir?

Java'da HashMap Nedir?

Java programlama dilinde verileri organize etmek, aramak ve işlemek yazılım geliştirme süreçlerinin temel taşlarından biridir. Standart diziler veya liste yapıları (ArrayList gibi) elemanları sayısal indeks numaraları (0, 1, 2…) üzerinden saklar. Ancak gerçek dünya senaryolarında bir veriye erişmek için sayısal indisler yerine kimlik numarası, kullanıcı adı veya ürün kodu gibi anlamlı belirteçler kullanmak gerekir. Bu noktada Java Collections Framework çatısı altında yer alan HashMap sınıfı devreye girer.

HashMap Nedir ve Hangi Amaçla Kullanılır?

HashMap, java.util paketinde bulunan ve Map arayüzünü (interface) uygulayan bir koleksiyon sınıfıdır. Verileri “Anahtar-Değer” (Key-Value) çiftleri halinde depolar. Buradaki temel fikir, her bir değere (value) ulaşmak için benzersiz bir anahtarın (key) kullanılmasıdır.

HashMap yapısının öne çıkan temel özellikleri şunlardır:

  • Anahtarlar benzersiz (unique) olmak zorundadır. Aynı anahtarla yeni bir değer eklenirse, eski değerin üzerine yazılır.
  • Değerler (values) yinelenen (duplicate) veriler içerebilir; farklı anahtarlar aynı değere işaret edebilir.
  • Bir adet null anahtara ve birden fazla null değere izin verir.
  • Elemanların belleğe eklenme sırasını garanti etmez; verilerin sırası zaman içinde iç düzenlemeler nedeniyle değişebilir.
  • İş parçacığı güvenliği (thread-safe) sağlamaz. Çok iş parçacıklı (multi-threaded) ortamlarda senkronizasyon harici olarak yönetilmelidir.

HashMap Arka Planda Nasıl Çalışır?

HashMap’in veri arama, ekleme ve silme işlemlerinde ortalama O(1) zaman karmaşıklığı sunmasının arkasında “Hashing” (özetleme) algoritması yatar.

HashMap bellekte “Bucket” (kova) adı verilen bir dizi üzerinde çalışır. Bir anahtar-değer çifti eklendiğinde şu adımlar gerçekleşir:

  • Eklenmek istenen anahtar nesnesinin hashCode() metodu çağrılır. Bu metot tamsayı bir özet değeri üretir.
  • Üretilen hash değeri, arka plandaki tablonun boyutuna göre modüler bir işlemden geçirilerek dizideki hangi kovaya (indekse) yerleşeceği hesaplanır.
  • Eğer iki farklı anahtar aynı kova indeksine denk gelirse “Hash Collision” (çakışma) oluşur. Java, aynı kovaya denk gelen elemanları birbirine bağlı liste (LinkedList) mantığıyla bağlar. Java 8 ile birlikte, bir kovadaki eleman sayısı belirli bir eşiği (varsayılan olarak 8) aştığında bu liste otomatik olarak kırmızı-siyah ağaca (Red-Black Tree) dönüştürülür. Bu optimizasyon arama süresini O(n) seviyesinden O(log n) seviyesine indirir.
  • Bir anahtara göre değer arandığında yine anahtarın hash kodu hesaplanır, ilgili kovaya gidilir ve kovadaki elemanlar equals() metodu ile karşılaştırılarak doğru nesne bulunur.

Bu mekanizma nedeniyle anahtar olarak kullanılan sınıfların equals() ve hashCode() metotlarını doğru ve tutarlı bir şekilde ezmesi (override etmesi) hayati önem taşır. String ve Integer gibi Java’nın yerleşik sınıfları bu metotları zaten doğru uyguladığı ve değiştirilemez (immutable) oldukları için anahtar olarak sıklıkla tercih edilir.

Temel Metotlar ve Kod Örneği

HashMap ile çalışırken en sık başvurulan metotlar put(), get(), containsKey(), remove() ve size() metotlarıdır.

Aşağıdaki örnekte kullanıcı kimlikleri ile kullanıcı adlarını tutan bir HashMap örneği yer almaktadır:

import java.util.HashMap;

public class HashMapOrnek {
    public static void main(String[] args) {
        HashMap<String, String> kullanicilar = new HashMap<>();

        // Veri ekleme
        kullanicilar.put("usr101", "Ahmet Yilmaz");
        kullanicilar.put("usr102", "Ayse Demir");
        kullanicilar.put("usr103", "Mehmet Kaya");

        // Var olan anahtara yeni deger atama (uzerine yazar)
        kullanicilar.put("usr101", "Ahmet Can Yilmaz");

        // Veri okuma
        String kullanici = kullanicilar.get("usr102");
        System.out.println("Sorgulanan Kullanici: " + kullanici);

        // Anahtar kontrolu
        if (kullanicilar.containsKey("usr103")) {
            System.out.println("usr103 sistemde kayitli.");
        }

        // Eleman silme
        kullanicilar.remove("usr103");

        // Eleman sayisi
        System.out.println("Toplam Kullanici: " + kullanicilar.size());
    }
}

Yukarıdaki kod bloğunda:

  • HashMap<String, String> tanımı ile hem anahtarın hem de değerin metin tabanlı olacağı belirtilmiştir.
  • put() metoduyla veriler eklenmiş, aynı anahtar (“usr101”) tekrar kullanıldığında eski değer güncellenmiştir.
  • get() metodu verilen anahtara ait değeri döndürmüştür; eğer anahtar bulunamasaydı null dönecekti.
  • containsKey() metodu harita içinde ilgili anahtarın olup olmadığını doğrulamıştır.
  • remove() ile kayıt silinmiş ve size() ile güncel eleman adedi ekrana yazdırılmıştır.

HashMap Üzerinde Gezinme (Iteration)

HashMap içerisindeki tüm verileri ekrana yazdırmak veya işlemek için farklı yaklaşımlar mevcuttur. Performans açısından hem anahtara hem de değere ihtiyaç duyulan durumlarda entrySet() kullanımı en verimli yoldur.

import java.util.HashMap;
import java.util.Map;

public class HashMapGezinme {
    public static void main(String[] args) {
        HashMap<String, Integer> stoklar = new HashMap<>();
        stoklar.put("Klavye", 45);
        stoklar.put("Fare", 120);
        stoklar.put("Monitor", 18);

        // entrySet kullanarak tum ciftler uzerinde donme
        for (Map.Entry<String, Integer> kayit : stoklar.entrySet()) {
            System.out.println("Urun: " + kayit.getKey() + " - Stok Adedi: " + kayit.getValue());
        }

        // Sadece anahtarlar uzerinde donme
        for (String urunAdi : stoklar.keySet()) {
            System.out.println("Mevcut Urun: " + urunAdi);
        }
    }
}

Bu örnekte yer alan entrySet() metodu, koleksiyondaki her bir anahtar-değer ikilisini temsil eden bir Map.Entry kümesi döndürür. Bu yöntem, her adımda haritadan yeniden get() sorgusu yapma maliyetini ortadan kaldırır. Yalnızca anahtarlar gerekliyse keySet(), yalnızca değerler gerekliyse values() metodu kullanılır.

HashMap Kullanırken Dikkat Edilmesi Gerekenler

  • HashMap sıralı değildir. Eğer verilerin ekleme sırasıyla tutulması gerekiyorsa LinkedHashMap, anahtarların doğal sıralamasıyla (veya bir Comparator ile) dizilmesi gerekiyorsa TreeMap tercih edilmelidir.
  • Çoklu iş parçacığı (concurrency) barındıran uygulamalarda HashMap veri bozulmalarına neden olabilir. Eşzamanlı işlemler için ConcurrentHashMap kullanımı en güvenli yoldur.
  • Kapasite ve doluluk faktörü (Load Factor) performansı etkiler. Varsayılan başlangıç kapasitesi 16, doluluk oranı ise 0.75’tir. Büyük hacimli verilerde yeniden boyutlandırma maliyetini azaltmak için başlangıç kapasitesi önceden tanımlanabilir.

Özet ve Sonraki Adımlar

Java’da HashMap, yüksek arama ve ekleme performansı sunan, anahtar-değer modelini temel alan en yaygın veri yapısıdır. Arka planda çalışan hashing mimarisini kavramak, olası performans darboğazlarının ve mantık hatalarının önüne geçmeyi sağlar.

Bir sonraki adımda, nesneleri HashMap anahtarı olarak kullanırken equals ve hashCode sözleşmesinin nasıl uygulanması gerektiğini inceleyebilir veya thread-safe mimariler için ConcurrentHashMap yapısının iç detaylarına geçiş yapabilirsiniz.

#collections framework#java#java hashmap#veri yapıları#yazılım geliştirme

Comments

No comments yet. Write the first comment.

Write a comment

Comments are published after admin approval.