Bir HashSet / HashMap öğesine yinelenen bir değer eklemek önceki değerin yerine geçiyor mu?


137

Lütfen aşağıdaki kod parçasını düşünün:

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

hs.size()HashSetyinelemelere izin vermediği için 1 verir, böylece yalnızca bir öğe depolanır.

Yinelenen öğeyi ekleyip eklemediğimizi bilmek istiyorum, o zaman önceki öğenin yerini mi alıyor yoksa basitçe eklemiyor mu?

Ayrıca, HashMapaynı dava için ne olacak ?

Yanıtlar:


247

Durumunda, HashMapeski değeri yenisiyle değiştirir.

Durumunda, HashSetöğe eklenmez.


1
Neyi kaçırdığımdan emin değilim, ancak kaynak kodu aksini gösteriyor gibi görünüyor mu? Onların desteğiyle bir kontrol yapmayın görüyoruz HashMapolmadığını görmek için keyzaten çağırmadan önce var olan putdesteğinde map?
mystarrocks

10
@mystarrocks: Anahtar, öğesinin öğesidir Setve asla put()işlemle değiştirilmez .
Keppil

1
ah şimdi anladım. Anahtarın unsuru Setolduğunu anladım, ancak sadece put()anahtarı değil, değeri geçersiz kılacağını fark ettim . Bu durumda, anahtarın yanına tekrar verilen değer aynıdır, bu da anahtarın var olup olmadığını kontrol etmek ve koymaktan daha iyi olabilir. Her iki durumda da, nasıl çalıştığını anlıyorum.
mystarrocks

Sadece merak ediyorum, HashMap ve HashSet neden böyle olmayı seçti?
Helin Wang

@HelinWang: Planlandığını düşünmüyorum, bunun sadece HashSeta şeklinde uygulanmasının bir etkisi olduğunu düşünüyorum HashMap. Sınıfların geliştiricilerinden biri değilseniz, bilmek zor.
Keppil

47

Bilmeniz gereken ilk şey, HashSeta gibi davranmasıdır Set, yani nesnenizi doğrudan eklediğiniz anlamına gelir HashSetve kopyaları içeremez. Sadece değerinizi doğrudan içine ekleyin HashSet.

Ancak, HashMapbir Maptürüdür. Bu, her giriş eklediğinizde bir anahtar / değer çifti eklediğiniz anlamına gelir.

İçinde HashMapyinelenen değerleriniz olabilir, ancak yinelenen anahtarlar olamaz. Gelen HashMapyeni girdinin eskisinin yerini alacaktır. En son giriş,HashMap .

HashMap ve HashSet arasındaki Bağlantıyı Anlama:

Unutmayın, HashMapyinelenen anahtarlar olamaz. Sahne arkasında HashSetbir kullanır HashMap.

A içine herhangi bir nesne eklemeye çalıştığınızda HashSet, bu giriş aslında sahnenin arkasında kullanılanla HashMapaynı HashMapolan bir anahtar olarak saklanır HashSet. Bu temelde yatan HashMapbir anahtar / değer çiftine ihtiyaç duyduğundan, bizim için bir kukla değer üretilir.

Şimdi aynı nesneyi başka bir yinelenen nesne eklemeye çalıştığınızda HashSet, yine HashMapaltında yatan bir anahtar olarak eklemeye çalışacaktır . Ancak, HashMapkopyaları desteklemez. Bu nedenle,HashSet yine de bu türden yalnızca bir değere sahip olunur. Bir yan not olarak, her yinelenen anahtar için, HashSet'e girişimiz için oluşturulan değer rastgele / kukla bir değer olduğundan, anahtar hiç değiştirilmez. anahtarın çıkarılması ve aynı anahtarın (kukla değer aynıdır) eklenmesi hiç mantıklı olmadığı için yok sayılır.

Özet:

HashMapyinelemeye izin verir values, ancak izin vermez keys. HashSetkopyalar içeremez.

Bir nesnenin eklenmesi başarıyla tamamlandı olup olmadığını oynamak ya da olmamak kontrol edebilirsiniz booleanAradığınızda döndürülen değeri .add() ve döndürür olmadığını görmek trueveya false. İade ederse true, bu yerleştirilmiştir.


HashMap allows duplicate valuesHashMap eski değeri yenisiyle değiştirir.
Alex78191

20

Dokümanlar bu konuda oldukça açıktır: HashSet.add gelmez değiştirin:

Zaten mevcut değilse, belirtilen öğeyi bu kümeye ekler. Daha resmi olarak, bu kümede e2 öğesi yoksa (e == null? E2 == null: e.equals (e2)) bu kümeye belirtilen e öğesini ekler. Bu küme zaten öğeyi içeriyorsa, çağrı kümeyi değiştirmeden bırakır ve false değerini döndürür.

Ama edecektir değiştirin:HashMap.put

Harita daha önce anahtar için bir eşleme içeriyorsa, eski değer değiştirilir.



1

Eğer yanılıyorsam beni düzeltin ama elde ettiğiniz dize ile "Merhaba" == "Merhaba" her zaman doğru gelmez (çünkü onlar mutlaka aynı nesne değildir).

1 yanıtını almanızın nedeni JVM'nin dizeleri nesneleri mümkün olduğunca yeniden kullanmasıdır. Bu durumda JVM, dize nesnesini yeniden kullanır ve böylece Hashmap / Hashset öğesinin üzerine yazar.

Ancak bu davranışı garanti etmezsiniz (çünkü aynı değere sahip "Hi" olan farklı bir dize nesnesi olabilir). Gördüğünüz davranış sadece JVM'nin optimizasyonundan kaynaklanmaktadır.


0

HashSet HashMap tarafından yedeklendiğinden önce Hash haritasındaki put yöntemini kontrol etmeniz gerekir

  1. Yinelenen değer eklediğinizde HashSet'e bir "String" deyin,
  2. Hashmap'a bir girdi ("one", PRESENT) eklenecek (kümeye eklenen tüm değerler için değer Object türündeyse "PRESENT" olacaktır)
  3. Hashmap girdiyi Haritaya ekler ve bu durumda "PRESENT" olan veya Giriş orada değilse null olan değeri döndürür.
  4. Daha sonra Hashset'in add yöntemi, Hashmap'tan döndürülen değer null değerine eşitse true değerini döndürür, aksi takdirde bir giriş zaten var demektir ...

0

Farklı söylemek için: Anahtarın zaten var olduğu bir HashMap'e bir anahtar / değer çifti eklediğinizde (bir anlamda hashvalue () aynı değeri und eşit () değerini verir, ancak iki nesne yine de çeşitli şekillerde farklılık gösterebilir ), anahtar değiştirilmez ancak değerin üzerine yazılır. Anahtar sadece hashvalue () almak ve onunla tabloda değeri bulmak için kullanılır. HashSet, bir HashMap'in anahtarlarını kullandığından ve sonuç olarak (kullanıcı için) gerçekten önemli olmayan rastgele değerler ayarladığından, Set Öğeleri de değiştirilmez.


0

HashMaptemelde Entrysonradan içeren içerir Key(Object)ve Value(Object).Internal HashSetolarak HashMapve HashMapbazılarınız zaten işaret ettiği gibi değerleri değiştirin ... ama gerçekten anahtarların yerini alıyor mu ??? Hayır .. ve buradaki hile. HashMapdeğerini temelde anahtar olarak tutar HashMapve değer sadece kukla bir nesnedir.Bu nedenle u HashMap'te aynı değeri yeniden oluşturmaya çalışırsanız (alttaki Haritadaki Anahtar) .Anahtar sadece kukla değeri değiştirir (HashSet Değeri).

HashSet Sınıfı için aşağıdaki koda bakın:

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

Burada e HashSet için değerdir, ancak alttaki map.and anahtarı için anahtar asla değiştirilmez. Umarım karışıklığı giderebilirim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.