Apakah menambahkan nilai duplikat ke HashSet / HashMap menggantikan nilai sebelumnya

141

Harap pertimbangkan potongan kode di bawah ini:

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

hs.size()akan memberikan 1 karena HashSettidak mengizinkan duplikat sehingga hanya satu elemen yang akan disimpan.

Saya ingin tahu apakah kita menambahkan elemen duplikat, lalu apakah itu menggantikan elemen sebelumnya atau tidak menambahkannya?

Juga, apa yang akan terjadi jika menggunakan HashMapkasus yang sama?

Anand
sumber

Jawaban:

251

Dalam kasus HashMap, ini menggantikan nilai lama dengan yang baru.

Dalam kasus HashSet, item tidak disisipkan.

Keppil
sumber
1
Tidak yakin apa yang saya lewatkan, tetapi kode sumber tampaknya menunjukkan sebaliknya? Saya melihat bahwa mereka tidak melakukan pemeriksaan di bagian belakang HashMapuntuk melihat apakah keysudah ada sebelum meminta putdukungan map?
mystarrocks
10
@ mystarrocks: Kuncinya adalah elemen dari Set, dan itu tidak pernah digantikan oleh put()operasi.
Keppil
1
ah saya mengerti sekarang. Saya mengerti bahwa kuncinya adalah elemen Set, tetapi baru menyadari bahwa put()hanya akan menimpa nilai, bukan kuncinya. Dalam hal ini, nilai yang sama diletakkan di samping kunci lagi, yang mungkin lebih baik atau tidak lebih baik daripada memeriksa apakah kunci ada dan meletakkan. Bagaimanapun, saya mengerti cara kerjanya.
mystarrocks
1
Penasaran saja, mengapa HashMap dan HashSet memilih demikian?
Helin Wang
@HelinWang: Saya rasa itu tidak direncanakan, saya pikir itu hanya efek dari HashSetpenerapan dalam bentuk file HashMap. Sulit untuk diketahui, kecuali Anda adalah salah satu pengembang kelas.
Keppil
47

Hal pertama yang perlu Anda ketahui adalah bahwa HashSetbertindak seperti a Set, yang berarti Anda menambahkan objek Anda langsung ke HashSetdan tidak dapat berisi duplikat. Anda cukup menambahkan nilai Anda secara langsung HashSet.

Namun, HashMapadalah Maptipe. Itu berarti setiap kali Anda menambahkan entri, Anda menambahkan pasangan nilai kunci.

Dalam HashMapAnda dapat memiliki nilai duplikat, tetapi bukan kunci duplikat. Di HashMapentri baru akan menggantikan yang lama. Entri terbaru akan berada di HashMap.

Memahami Tautan antara HashMap dan HashSet:

Ingat, HashMaptidak boleh memiliki kunci duplikat. Di belakang layar HashSetmenggunakan a HashMap.

Saat Anda mencoba menambahkan objek apa pun ke dalam HashSet, entri ini sebenarnya disimpan sebagai kunci di HashMap- sama HashMapyang digunakan di belakang layar HashSet. Karena dasar ini HashMapmembutuhkan pasangan nilai kunci, nilai dummy dibuat untuk kita.

Sekarang ketika Anda mencoba memasukkan objek duplikat lain ke dalam objek yang sama HashSet, itu akan mencoba untuk memasukkannya lagi sebagai kunci di HashMapbawahnya. Namun, HashMaptidak mendukung duplikat. Karenanya, HashSetmasih akan menghasilkan hanya satu nilai dari tipe itu. Sebagai catatan tambahan, untuk setiap kunci duplikat, karena nilai yang dihasilkan untuk entri kita di HashSet adalah nilai acak / tiruan, kunci tersebut tidak diganti sama sekali. itu akan diabaikan karena menghapus kunci dan menambahkan kembali kunci yang sama (nilai dummy adalah sama) tidak akan masuk akal sama sekali.

Ringkasan:

HashMapmemungkinkan duplikat values, tetapi tidak keys. HashSettidak boleh berisi duplikat.

Untuk bermain dengan apakah penambahan suatu objek berhasil diselesaikan atau tidak, Anda dapat memeriksa booleannilai yang dikembalikan saat Anda memanggil .add() dan melihat apakah itu kembali trueatau false. Jika dikembalikan true, itu sudah dimasukkan.

Jimmy
sumber
HashMap allows duplicate valuesHashMap menggantikan nilai lama dengan yang baru.
Alex78191
21

The docs cukup jelas tentang hal ini: HashSet.add tidak mengganti:

Menambahkan elemen yang ditentukan ke set ini jika belum ada. Lebih formal, menambahkan elemen e yang ditentukan ke set ini jika set ini tidak berisi elemen e2 sedemikian rupa (e == null? E2 == null: e.equals (e2)). Jika set ini sudah berisi elemen, panggilan membiarkan set tidak berubah dan mengembalikan nilai false.

Tapi akan menggantikan:HashMap.put

Jika peta sebelumnya berisi pemetaan untuk kunci tersebut, nilai lama akan diganti.

pb2q
sumber
4

Ini kasus HashSet, itu TIDAK menggantikannya.

Dari dokumen:

http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )

"Menambahkan elemen yang ditentukan ke set ini jika belum ada. Secara formal, menambahkan elemen e yang ditentukan ke set ini jika set ini tidak berisi elemen e2 sehingga (e == null? E2 == null: e.equals ( e2)). Jika set ini sudah berisi elemen, panggilan meninggalkan set tidak berubah dan mengembalikan false. "

Bob Provencher
sumber
1

Koreksi saya jika saya salah tetapi yang Anda maksud adalah bahwa dengan string, "Hi" == "Hi" tidak selalu benar (karena mereka belum tentu objek yang sama).

Alasan Anda mendapatkan jawaban 1 adalah karena JVM akan menggunakan kembali objek string jika memungkinkan. Dalam hal ini JVM menggunakan kembali objek string, dan dengan demikian menimpa item tersebut di Hashmap / Hashset.

Tetapi Anda tidak dijamin untuk perilaku ini (karena ini bisa menjadi objek string berbeda yang memiliki nilai "Hi" yang sama). Perilaku yang Anda lihat hanya karena pengoptimalan JVM.

Nick Rippe
sumber
1

HashMappada dasarnya berisi Entryyang selanjutnya berisi Key(Object)dan. Secara Value(Object)internal HashSetadalah HashMapdan HashMapmemang mengganti nilai seperti yang telah Anda tunjuk..tetapi apakah itu benar-benar menggantikan kunci ??? Tidak .. dan itulah triknya di sini. HashMapmempertahankan nilainya sebagai kunci yang mendasari HashMapdan nilai hanyalah objek dummy. Jadi jika Anda mencoba memasukkan kembali Nilai yang sama di HashMap (Kunci di Peta yang mendasari). Itu hanya menggantikan nilai dummy dan bukan Kunci (Nilai untuk HashSet).

Lihat kode di bawah ini untuk Kelas HashSet:

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

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

Di sini e adalah nilai untuk HashSet tetapi kunci untuk peta yang mendasarinya. Dan kunci tidak pernah diganti. Semoga saya bisa menghilangkan kebingungan itu.

Kunal Kumar
sumber
0

Anda perlu memeriksa metode put di peta Hash terlebih dahulu karena HashSet didukung oleh HashMap

  1. Saat Anda menambahkan nilai duplikat, ucapkan String "Satu" ke dalam HashSet,
  2. Entri ("satu", PRESENT) akan dimasukkan ke dalam Hashmap (untuk semua nilai yang ditambahkan ke dalam set, nilainya akan menjadi "PRESENT" yang jika bertipe Object)
  3. Hashmap menambahkan entri ke dalam Peta dan mengembalikan nilainya, yang dalam hal ini "PRESENT" atau null jika Entri tidak ada.
  4. Metode tambah Hashset kemudian mengembalikan nilai true jika nilai yang dikembalikan dari Hashmap sama dengan nol jika tidak salah yang berarti entri sudah ada ...
pisau
sumber
0

Untuk mengatakannya secara berbeda: Ketika Anda memasukkan key-value-pair ke dalam HashMap di mana kuncinya sudah ada (dalam arti hashvalue () memberikan nilai yang sama und equal () benar, tetapi kedua objek masih bisa berbeda dalam beberapa cara ), kuncinya tidak diganti tetapi nilainya ditimpa. Kuncinya hanya digunakan untuk mendapatkan hashvalue () dan menemukan nilai dalam tabel dengannya. Karena HashSet menggunakan kunci HashMap dan menetapkan nilai sewenang-wenang yang tidak terlalu penting (bagi pengguna) sebagai akibatnya, Elemen Set juga tidak diganti.

Marco Rothley
sumber