get
dalam put
HashMap?”. Di sini saya akan cuba menerangkan fungsi dalaman menggunakan contoh mudah. Tanpa pergi ke terlalu banyak teori, kami akan mulakan dengan contoh supaya anda boleh memahami dengan lebih baik dan kemudian melihat cara kaedah berfungsi di Jawa get
juga . put
Mari kita ambil contoh yang sangat mudah. Kami mempunyai kelas Country
(bahasa Inggeris "negara"), kami akan menggunakan objek kelas Country
sebagai kunci, dan nama ibu negara ini sebagai nilainya. Di bawah ialah contoh untuk membantu kami memahami cara pasangan nilai kunci akan disimpan dalam peta cincang.
1. Country.java
package org.arpit.javapostsforlearning;
public class Country {
String name;
long population;
public Country(String name, long population) {
super();
this.name = name;
this.population = population;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population = population;
}
// если длина имени в an objectе Country - четное число,
// то возвращаем 31(любое случайное число), а если нечетное - 95 (любое случайное число).
// указанный ниже метод - это не самый лучший способ генерации хеш-codeа,
// но мы воспользуемся им для более четкого понимания хеш-карт.
@Override
public int hashCode() {
if(this.name.length()%2==0)
return 31;
else
return 95;
}
@Override
public boolean equals(Object obj) {
Country other = (Country) obj;
if (name.equalsIgnoreCase((other.name)))
return true;
return false;
}
}
Jika anda ingin memahami dan mengetahui lebih lanjut tentang kaedah hashcode
dan persamaan, anda boleh mengikuti pautan ini .
2. HashMapStructure.java(kelas utama)
import java.util.HashMap;
import java.util.Iterator;
public class HashMapStructure {
/**
* @author Arpit Mandliya
*/
public static void main(String[] args) {
Country india=new Country("India",1000);
Country japan=new Country("Japan",10000);
Country france=new Country("France",2000);
Country russia=new Country("Russia",20000);
HashMap<country,string> countryCapitalMap=new HashMap<country,string>();
countryCapitalMap.put(india,"Delhi");
countryCapitalMap.put(japan,"Tokyo");
countryCapitalMap.put(france,"Paris");
countryCapitalMap.put(russia,"Moscow");
Iterator<country> countryCapitalIter=countryCapitalMap.keySet().iterator();//установите
//debug-точку на этой строке(23)
while(countryCapitalIter.hasNext())
{
Country countryObj=countryCapitalIter.next();
String capital=countryCapitalMap.get(countryObj);
System.out.println(countryObj.getName()+"----"+capital);
}
}
}
Sekarang tetapkan titik putus ke baris 23 dan jalankan run -> debug as-> aplikasi java (nota penterjemah - sah untuk Eclipse). Program ini akan menghentikan pelaksanaan pada baris 23, selepas itu klik kanan pada countryCapitalMap dan pilih tonton . Anda akan melihat jadual seperti ini: Di sini kita melihat perkara berikut:
-
Terdapat tatasusunan
Entry[]
16 sel bernamatable
; -
Tatasusunan ini menyimpan objek kelas
Entry
. KelasHashMap
mempunyai kelas dalaman -Entry
. Dan contoh kelas ini ialah pasangan nilai kunci. Mari kita lihat struktur kelasEntry
: -
Setiap kali kami cuba mencipta pasangan nilai kunci dalam peta cincang, objek kelas akan dibuat untuk pasangan itu
Entry
dan ia akan disimpan dalam jadual di atasEntry[]
. Dan kini anda sepatutnya tertanya-tanya di mana sebenarnya dalam jadual ini objek ini akan ditulis (di sel mana). Untuk kunci dalam pasangan nilai kunci, kod cincang dikira menggunakanhashcode()
. Dan kod cincang ini digunakan untuk mengira nombor sel jadualEntry[]
; -
Sekarang jika anda melihat sel 10 jadual, anda akan melihat objek kelas
Entry
bernamaHashMap$Entry
; - Kami menambah 4 pasangan nilai kunci, tetapi terdapat hanya 2 dalam tatasusunan!!! Ini kerana jika 2 objek mempunyai kod cincang yang sama, maka ia akan disimpan dalam sel yang sama. Tetapi bagaimana? Objek akan disimpan sebagai senarai terpaut (
LinkedList
).
static class Entry implements Map.Entry
{
final K key;
V value;
Entry next;
final int hash;
...//продолжение codeа
}
Hashcode for Japan = 95 так How длина слова Japan имеет нечетное количество букв.
Hashcode for India = 95 так How длина слова India имеет нечетное количество букв.
HashCode for Russia = 31 так How длина слова Russia имеет четное количество букв.
HashCode for France = 31 так How длина слова France имеет четное количество букв.
Angka berikut akan menerangkan idea senarai terpaut: Sekarang anda sudah mempunyai pemahaman tentang struktur peta cincang, mari kita beralih kepada kaedah put
dan get
.
Letak:
Mari lihat bagaimana kaedah ini digunakan:/**
* Метод связывает указанное meaning с указанным ключом в данной хэш-карте. Если
* карта до этого уже содержала некоторое meaning, соответствующее этому ключу,
* то старое meaning заменяется на указанное.
* @param key
* ключ, с которым связывается указанное meaning
* @param value
* meaning, связываемое с указанным ключом
* @возвращает meaning связанное с <tt>ключом</tt>, or <tt>null</tt>,
* если ниHowое meaning не соответствует <tt>ключу</tt>. ( Возврат <tt>null</tt>
* может так же говорить о том, что в карте заведомо <tt>null</tt> был связан с
* <tt>ключом</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<k , V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
Sekarang mari kita cuba memahami kod ini langkah demi langkah:
-
Kami menyemak objek
key
untuk kesaksamaannull
. Jika ya, maka objekkey
akan disimpan di lokasitable[0]
kerana kod cincang untuknull
sentiasa 0; -
key
Seterusnya, kami memanggil kaedah objekhashcode()
, yang akan mengira kod cincangnya. Kod cincang ini digunakan untuk menentukan sel tatasusunan di mana objek kelas akan disimpanEntry
. Kadang-kadang ia berlaku bahawa fungsi inihashcode
tidak ditulis dengan sangat mahir, jadi pembangun JDK mencipta fungsi yang berbeza -hash()
, yang mengambil kod cincang yang dikira sebelumnya sebagai hujah. Jika anda berminat untuk membaca tentang fungsi ini dengan lebih terperinci, anda boleh ikuti pautan ; -
indexFor(hash,table.length)
digunakan untuk menentukan sel tertentu dalam tatasusunantable
di mana objek kelas akan ditakrifkan untuk disimpanEntry
; -
Seperti yang kita lihat dalam contoh kami, jika dua objek
key
mempunyai kod cincang yang sama (keadaan ini dikenali sebagai perlanggaran), maka ia akan disimpan dalam bentuk senarai terpaut. Oleh itu, pada peringkat ini kami mengulangi senarai kami: -
jika sel yang baru dikira kosong, maka objek kelas
Entry
akan disimpan terus ke dalam sel ini; -
jika sel ini sudah mengandungi beberapa objek, kemudian lelaran kepada elemen yang medannya
next
sama dengannull
. Selepas ini, objek kelas kamiEntry
menjadi seterusnya dalam senarai; -
bagaimana jika kita menambah objek yang sama
key
sekali lagi? Secara logiknya, ia sepatutnya menggantikan nilai lama. Ya, ia akan jadi begitu. Semasa lelaran, kekunci akan dibandingkan menggunakan kaedahequals()
(key.equals(k)
). Jika hasilnya benar, maka nilai lama akan digantikan dengan nilai objek semasaEntry
.
Dapatkan:
Sekarang mari kita lihat aplikasi kaedah tersebut/**
* returns meaning, которое соответствует указанному ключу, or {@code null}, если
* данная карта не содержит пары с указанным ключом.
*
*
* <p>
* Более точно, если в данной карте содержится такой ключ {@code k}
* с соответствующим ему meaningм {@code v}, что {@code (key==null ? k==null : key.equals(k))},
* то метод возвращает {@code v}; в противном случае возвращается {@code null}.
* (может быть не более одной такой пары)
*
* </p><p>
* Возвращенное meaning {@code null} не <i>обязательно</i> говорит о том, что
* в карте нет пары с таким указанным ключом; а возможно, что в карте однозначно
* указано соответствие этого ключа со meaningм {@code null}.
* Можно воспользоваться операцией {@link #containsKey containsKey}, чтобы
* отличить эти два случая
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
Kini setelah anda memahami cara kaedah put berfungsi dalam peta hash, memahami cara kaedah put berfungsi adalah
get
sangat mudah. Apabila anda menghantar sebarang kunci kepada kaedah untuk mendapatkan nilai daripada peta cincang:
-
Sebuah objek
Ekey diuji untuk kesaksamaan null
. Jika ya, maka nilai objek yang disimpan dalam sel akan dikembalikantable[0]
; -
Objek utama mempunyai kaedah yang dipanggil
hashcode()
yang mengira kod cincang; -
indexFor(hash,table.length)
digunakan untuk menentukan sel tatasusunan tertentutable
untuk mengambil objek kelasEntry
; -
Selepas menerima nombor sel tatasusunan,
table
ia akan berulang melalui senarai dan membandingkan kekunci menggunakan kaedahequals()
. Jika hasilnya benar, maka nilai objek akan dikembalikanEntry
, jika tidak -null
.
Perkara yang perlu diingat:
-
Kelas
HashMap
mempunyai kelas dalamanEntry
yang menyimpan pasangan nilai kunci; -
Objek kelas
Entry
disimpan dalam tatasusunanEntry[ ]
dipanggiltable
; -
Sel tatasusunan dipanggil baldi dan menyimpan elemen pertama senarai terpaut;
-
Kaedah
hashcode()
objekkey
digunakan untuk mencari baldi objek kelas iniEntry
; -
Jika kunci dua objek mempunyai kod cincang yang sama, ia akan disimpan dalam baldi tatasusunan yang sama
table
; -
Kaedah
equals()
objekkey
digunakan untuk mengesahkan keunikannya; -
Kaedah
equals()
danhashcode()
objekvalue
tidak digunakan sama sekali.
GO TO FULL VERSION