HashMap#values()
metodu üzerinden bir HashMap
üzerindeki değerleri alabiliriz. Aldığımız bu değerlerin hash code'ları üzerinden bir hesaplamaya girişeceksek bu durumda values().hashCode() metodu beklediğimiz sonuçları dönmeyebilir. Şöyle ki, farklı HashMap
nesnelerinde aynı anahtar-değer ikilileri (key-value pair) olsa dahi o HashMap
nesneleri üzerinden yapılacak values().hashCode()
çağrıları farklı sonuçlar üretir.
Map<String, String> map1 = new HashMap<String, String>();
map1.put("key1", "value1");
map1.put("key2", "value2");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("key1", "value1");
map2.put("key2", "value2");
assert map1.hashCode() == map2.hashCode();
assert map1.values().hashCode() != map2.values().hashCode()
Örnekte de görülebildiği gibi, HashMap#hashCode()
ile HashMap#values()#hashCode()
farklı sonuçlar üretir. Bunun nedenini HashMap
kaynak kodlarına bakarak görebiliriz.
HashMap
, AbstractMap
'i miras alır ve hash metodu olarak AbstractMap#hashCode
metodunu kullanır.
AbstractMap#hashCode
:
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
Bu metod, map içerisindeki tüm kayıtları dolaşır ve her kayıttan ürettiği hash sonuçlarını toplar. Bu demektir ki iki farklı HashMap nesnesinde aynı anahtar-değer ikilileri varsa bu durumda iki map'in hash değerleri eşit olur.
Fakat HashMap#values
metodunun kaynak kodlarına bakarsak
public Collection<V> values() {
Collection<V> vs;
return (vs = values) == null ? (values = new Values()) : vs;
}
Bir map nesnesinin values
metodu ilk çağrıldığında values alanı (field) null
olduğu için values = new Values()
bölümü çalıştırılır. Values
sınıfı hashCode
metodu olarak Object
sınıfındaki ön tanımlı metodu miras alır ve dolayısıyla map'in sahip olduğu değerlere bakmaz. Bu durumda yeni bir nesne üzerinden çağrılan hashCode
metodu farklı sonuç döner. Bu hashCode değeri values alanından hesaplandığı için, aynı map'e yapılan ikinci values()
çağrısında önceden oluşturulmuş nesne gönderilir ve bu durumda hashCode aynı kalır.
Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
map.values() // önceden values() çağrısı yapılmadığı için new Values() üzerinden yeni Values nesnesi oluşturulur.
map.values() // ikinci çağrıda ise önceki çağrı üzerinden oluşturulan Values nesnesi döndürülür.
Detaylı bilgi: http://mindprod.com/jgloss/hashcode.html