Skip to content

Instantly share code, notes, and snippets.

@baybatu
Last active January 26, 2016 07:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baybatu/37d1b92685b967dd8908 to your computer and use it in GitHub Desktop.
Save baybatu/37d1b92685b967dd8908 to your computer and use it in GitHub Desktop.
HashMap#values() çağrılarında hashCode metoduna dikkat!

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment