Karamihan sa inyo ay sasang-ayon na
Maaari kang magbasa ng higit pa tungkol dito: Paggawa gamit ang hashCode at katumbas na pamamaraan sa Java
HashMap
, ngayon, ang pinakapaboritong paksa para sa talakayan sa panahon ng mga panayam. Minsan nagkaroon ako ng mga katulad na talakayan sa aking mga kasamahan at talagang nakatulong ito. Ngayon ay magkakaroon ako ng ganoong talakayan sa iyo. Ipinapalagay ko na kung interesado ka sa mga panloob at gawain ng HashMap, alam mo na ang mga pangunahing kaalaman ng HashMap , kaya laktawan ko ang bahaging iyon. Ngunit kung bago ka dito, iminumungkahi kong magtungo ka sa site ng Java Docs . Bago tayo magpatuloy, lubos kong inirerekumenda na tingnan mo ang aking nakaraang artikulo: Paggawa gamit ang hashCode at ang katumbas na pamamaraan sa Java. Mga nilalaman ng artikulong ito:
- Ang tanging posibleng sagot.
- Ano ang Hashing.
- Medyo tungkol sa klase
Entry
. - Ano ang ginagawa ng
put()
. - Paano gumagana ang pamamaraan
get()
. - Mga Tala
Ang tanging posibleng sagot
Kung may humihiling sa akin na ipaliwanag " Paano gumagana ang HashMap?" ", Sasagot lang ako: " Ayon sa mga prinsipyo ng Hashing ." Hindi ito maaaring maging mas simple. Upang maunawaan ito at makakuha ng pinahabang sagot, kailangan mong tiyaking alam mo ang mga pangunahing kaalaman sa Hashing. tama?Ano ang Hashing
Ang pag-hash sa pinakasimpleng anyo nito ay isang paraan ng pag-convert ng anumang variable/object sa isang natatanging code pagkatapos maglapat ng anumang formula/algorithm sa kanilang mga katangian. Ang isang tunay na hash function ay dapat sumunod sa sumusunod na panuntunan: Ang isang hash function ay dapat magbalik ng parehong hash code sa tuwing ito ay inilapat sa pareho o pantay na mga bagay. Sa madaling salita, dapat ibalik ng dalawang magkaparehong bagay ang parehong mga hash code.Tandaan: Ang lahat ng mga bagay sa java ay nagmamana ng karaniwang pagpapatupad hashCode() ng function na inilarawan sa klase Object . Ang function na ito ay nagbabalik ng hash code na nakuha sa pamamagitan ng pag-convert ng panloob na address ng isang bagay sa isang numero, na humahantong sa paglikha ng isang natatanging code para sa bawat indibidwal na bagay. |
Medyo tungkol sa Entry class
Sa pamamagitan ng kahulugan, ang mapa ay "isang bagay na nag-iimbak ng mga halaga at susi nang magkapares." Medyo simple, tama? Kaya, dapat mayroong ilang uri ng mekanismo sa HashMap na nag-iimbak ng mga pares ng Mga Halaga at Susi? Sagot - Oo.HashMap
ay may panloob na klase Entry
na ganito ang hitsura:
static class Entry implements Map.Entry
{
final K key;
V value;
Entry next;
final int hash;
...//остальной code тут…
}
Naturally, ang klase Entry
ay may Key at Value na nakaimbak bilang mga katangian. Ang susi ay minarkahan bilang final
at nakikita rin namin ang dalawang karagdagang field: next
at hash
. Susubukan naming maunawaan ang layunin ng mga larangang ito habang umuusad ang artikulo.
Ano ang ginagawa ng Java put() method?
Bago tayo sumisid sa pagpapatupad ng methodput()
, napakahalagang maunawaan na ang mga instance ng isang klase Entry
ay nakaimbak sa isang array. Tinutukoy ng klase ng HashMap ang variable na ito bilang:
/**
* Размер таблицы, изменяется при необходимости. Длина всегда должна быть
* кратна двум!
*/
transient Entry[] table;
Ngayon tingnan ang code ng pagpapatupad ng pamamaraan put()
:
/**
* Связывает определенное meaning с определенным ключом в этой карте(map).
* Если карта перед этим содержала meaning для данного ключа, это meaning
* заменится на новое.
*
* @param key
* ключ с которым указанное meaning должно быть связано.
* @param value
* meaning которое должно быть связано с ключом.
* @return вернет предыдущее meaning связанное с key, or null
* если не было значений связанных с key. (Вернет null
* так же, если перед этим key был связан со meaningм null)
*/
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;
}
Alamin natin ito nang hakbang-hakbang:
- Una sa lahat, sinusuri namin kung umiiral ang susi. Kung ang susi ay hindi umiiral (
null
), ang halaga ay inilalagay sa talahanayan sa posisyong zero dahil ang hash code para sa halaga aynull
,это – всегда 0
. - Sa susunod na hakbang, ang halaga ng hash ay kinakalkula gamit ang hash code ng key na nakuha sa pamamagitan ng pagtawag sa pamamaraan
hashCode()
. Ang hash value na ito ay ginagamit upang kalkulahin ang posisyon sa array kung saan ilalagay ang objectEntry
. Ipinapalagay ng mga taga-disenyo ng JDK na ang isang hindi magandang nakasulat na functionhashCode()
ay maaaring magbalik ng hash value na masyadong mataas o masyadong mababa. Upang malutas ang problemang ito, nagpakilala sila ng isa panghash()
function at ipinasa dito ang hash value ng isang bagay upang gawing tumugma ang hash value sa laki ng array. - Ngayon ang function ay tinatawag
indexFor(hash, table.length)
upang kalkulahin ang eksaktong posisyon kung saan ang bagay ay ilalagayEntry
. - Dito nagsisimula ang pangunahing bahagi. Ngayon, batay sa kung ano ang alam namin na - dalawang hindi pantay na mga bagay ay maaaring magkaroon ng pantay na hash code, itatanong namin ang tanong: Ang dalawang magkaibang mga bagay ay ilalagay sa parehong posisyon sa [bucket] array? Ang sagot ay
LinkedList
. Kung naaalala mo, ang klaseEntry
ay may katangian na "next
". Palaging tumuturo ang katangiang ito sa susunod na bagay sa chain. Ganito talaga ang ugaliLinkedList
.
Entry
ay naka-imbak sa form LinkedList
. Kapag ang isang bagay Entry
ay ilalagay sa isang partikular na lokasyon, ang HashMap ay tumitingin upang makita kung mayroon nang entry sa lokasyong iyon. Kung walang entry, kung gayon ang bagay ay inilalagay sa posisyong ito. Kung, gayunpaman, mayroon nang isang bagay sa posisyong ito, ang susunod na katangian ay susuriin. Kung ito ay bumalik null
at ang kasalukuyang bagay Entry
ay magiging susunod na link sa LinkedList
. Kung ang susunod na variable ay hindi null
, ang pamamaraan ay paulit-ulit para sa susunod na isa hanggang sa ito ay mahanap null
. Paano kung maglagay tayo ng isa pang bagay na may ibang halaga ngunit may parehong susi tulad ng dati? Sa lohikal na paraan, dapat itong magresulta sa pagpapalit ng lumang halaga. Paano ito nangyayari? Sa pangkalahatan, pagkatapos matukoy ang posisyon ng isang bagay Entry
, habang binabagtas LinkedList
ang kinakalkula na posisyon, HashMap
tinatawag nito ang key compare method para sa bawat object Entry
. Ang lahat ng Entry
mga bagay na ito LinkedList
ay maaaring may magkatulad na hash code, ngunit equals()
susuriin ng pamamaraan ang tunay na pagkakapareho. Papalitan lamang nito ang halaga sa loob ng Entry
. Kaya, ginagarantiyahan ng HashMap ang pagiging natatangi ng lahat ng mga susi.
Paano gumagana ang Java get() method?
Ngayon ay mayroon na tayong ideya kung paano iniimbak ang mga pares ng key-value saHashMap
. Ang susunod na malaking tanong ay: Ano ang mangyayari kapag ang isang bagay ay naipasa mula sa isang HashMap patungo sa isang pamamaraan get()
? Paano natutukoy ang halaga ng isang bagay? Dapat na alam na natin ang sagot, dahil ang paraan kung saan natutukoy ang pagiging natatangi ng isang susi sa pamamaraan put()
ay may parehong lohika na nalalapat sa pamamaraan get()
. Kapag HashMap
natukoy na nito ang susi ng bagay na ipinasa bilang argumento, ibinabalik lamang nito ang halaga ng katumbas na Entry
. Kung walang mahanap na tugma, get()
babalik ang paraan null
. Tingnan natin ang code:
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;
}
Ang code sa itaas ay katulad ng pamamaraan put()
hanggang sa puntong ito if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
. Pagkatapos nito ay ibinabalik lamang nito ang halaga ng bagay.
Mga Tala
- Ang istraktura ng data na maiimbak sa isang bagay
Entry
ay isang array na may pangalantable
at isang uriEntry
. - Ang bawat indibidwal na posisyon sa array ay tinatawag na bucket dahil maaari itong maglaman ng unang elemento
LinkedList
ng mga bagayEntry
. hashCode()
Ang susi ay kinakailangan upang makalkula ang posisyon ng bagayEntry
.equals()
Ang susi ay ginagamit upang suriin ang pagiging natatangi ng susi sa mapa(map
).hashCode()
atequals()
Ang mga halaga ay hindi ginagamit sa mga pamamaraanget()
atset()
saHashMap
.- Ang hash code para sa mga key na may value
null
ay palaging 0. At ang naturang objectEntry
ay palaging iimbak sa zero na posisyon ng array.
GO TO FULL VERSION