get
sa put
HashMap?”. Dito susubukan kong ipaliwanag ang panloob na pag-andar gamit ang isang simpleng halimbawa. Nang walang masyadong maraming teorya, magsisimula tayo sa isang halimbawa upang mas maunawaan mo at pagkatapos ay makita mo get
rin kung paano gumagana ang mga pamamaraan put
sa Java . Kumuha tayo ng isang napakasimpleng halimbawa. Mayroon kaming klase Country
(Ingles na "bansa"), gagamitin namin ang class object Country
bilang susi, at ang pangalan ng kabisera ng bansang ito bilang halaga. Nasa ibaba ang isang halimbawa upang matulungan kaming maunawaan kung paano iimbak ang isang pares ng key-value sa isang hash map.
1. Bansa.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;
}
}
Kung gusto mong maunawaan at matuto nang higit pa tungkol sa mga pamamaraan hashcode
at katumbas, maaari mong sundan ang link na ito .
2. HashMapStructure.java(pangunahing klase)
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);
}
}
}
Ngayon itakda ang breakpoint sa linya 23 at patakbuhin ang run -> debug as-> java application (tala ng tagasalin - wasto para sa Eclipse). Ihihinto ng programa ang pagpapatupad sa linya 23, pagkatapos ay i-right click sa countryCapitalMap at piliin ang panoorin . Makakakita ka ng isang talahanayan na tulad nito: Dito makikita natin ang sumusunod:
-
Mayroong isang hanay
Entry[]
ng 16 na mga cell na pinangalanangtable
; -
Ang array na ito ay nag - iimbak ng mga bagay ng klase
Entry
. Ang klaseHashMap
ay may panloob na klase -Entry
. At ang mga instance ng klase na ito ay key-value pairs. Tingnan natin ang istraktura ng klaseEntry
: -
Sa tuwing susubukan naming gumawa ng key-value pair sa isang hash map, gagawa ng class object para sa pares na iyon
Entry
at ito ay maiimbak sa talahanayan sa itaasEntry[]
. At ngayon dapat kang magtaka kung saan eksakto sa talahanayang ito ang bagay na ito ay isusulat (kung saang cell). Para sa isang key sa isang key-value pair, ang isang hash code ay kinakalkula gamit anghashcode()
. At ang hash code na ito ay ginagamit upang kalkulahin ang numero ng cell ng talahanayanEntry[]
; -
Ngayon, kung titingnan mo ang cell 10 ng talahanayan, makikita mo ang isang object ng klase
Entry
na pinangalanangHashMap$Entry
; - Nagdagdag kami ng 4 na pares ng key-value, ngunit 2 lang ang nasa array!!! Ito ay dahil kung ang 2 bagay ay may parehong hash code, sila ay maiimbak sa parehong cell. Pero paano? Ang mga bagay ay maiimbak bilang isang naka-link na listahan (
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 имеет четное количество букв.
Ang sumusunod na figure ay magpapaliwanag ng ideya ng isang naka-link na listahan: Ngayon na mayroon ka nang pag-unawa tungkol sa istraktura ng mga hash na mapa, lumipat tayo sa put
at mga pamamaraan get
.
Ilagay:
Tingnan natin kung paano ginagamit ang pamamaraang ito:/**
* Метод связывает указанное 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;
}
Ngayon, subukan nating maunawaan ang code na ito nang hakbang-hakbang:
-
Sinusuri namin ang bagay
key
para sa pagkakapantay-pantaynull
. Kung gayon, ang bagaykey
ay maiimbak sa lokasyontable[0]
dahil ang hash code para sanull
ay palaging 0; -
Susunod, tinatawag namin ang object's
key
methodhashcode()
, na kakalkulahin ang hash code nito. Ang hash code na ito ay ginagamit upang matukoy ang array cell kung saan iimbak ang class objectEntry
. Minsan nangyayari na ang function na itohashcode
ay hindi nakasulat nang napakahusay, kaya ang mga developer ng JDK ay lumikha ng ibang function -hash()
, na kumukuha ng dating kinakalkula na hash code bilang argumento. Kung interesado kang basahin ang tungkol sa function na ito nang mas detalyado, maaari mong sundin ang link ; -
indexFor(hash,table.length)
ginagamit upang tukuyin ang isang tiyak na cell sa arraytable
kung saan ang isang bagay ng klase ay tutukuyin upang maiimbakEntry
; -
Tulad ng nakita natin sa aming halimbawa, kung ang dalawang bagay
key
ay may parehong hash code (kilala ang sitwasyong ito bilang isang banggaan), kung gayon sila ay maiimbak sa anyo ng isang naka-link na listahan. Samakatuwid, sa yugtong ito inuulit namin ang aming listahan: -
kung ang bagong kalkuladong cell ay walang laman, ang class object
Entry
ay direktang ise-save sa cell na ito; -
kung ang cell na ito ay naglalaman na ng ilang bagay, pagkatapos ay umuulit sa elemento na ang field ay
next
katumbas ngnull
. Pagkatapos nito, ang aming class objectEntry
ay magiging susunod sa listahan; -
paano kung idagdag natin
key
muli ang parehong bagay? Logically, dapat nitong palitan ang lumang halaga. Oo, magiging gayon. Sa panahon ng pag-ulit, ihahambing ang mga susi gamit angequals()
(key.equals(k)
) na pamamaraan. Kung totoo ang resulta, ang lumang halaga ay papalitan ng halaga ng kasalukuyang bagayEntry
.
Kunin:
Ngayon tingnan natin ang aplikasyon ng pamamaraan/**
* 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;
}
Ngayon na mayroon ka nang pag-unawa sa kung paano gumagana ang paraan ng put sa mga hashmap, ang pag-unawa kung paano gumagana ang paraan ng put ay
get
napakasimple. Kapag nagpasa ka ng anumang key sa isang paraan para makakuha ng value mula sa hash map:
-
Isang bagay
Ang Ekey ay nasubok para sa pagkakapantay-pantay null
. Kung gayon, ang halaga ng bagay na nakaimbak sa cell ay ibabaliktable[0]
; -
Ang pangunahing bagay ay may tinatawag na pamamaraan
hashcode()
na kinakalkula ang hash code; -
indexFor(hash,table.length)
ginagamit upang matukoy ang isang tiyak na array celltable
kung saan kukuha ng isang bagay ng klaseEntry
; -
Pagkatapos matanggap ang array cell number,
table
ito ay umulit sa listahan at ihahambing ang mga key gamit ang pamamaraanequals()
. Kung totoo ang resulta, ibabalik ang halaga ng bagayEntry
, kung hindi -null
.
Bagay na dapat alalahanin:
-
Ang klase
HashMap
ay may panloob na klaseEntry
na nag-iimbak ng mga pares ng key-value; -
Ang mga bagay ng klase
Entry
ay naka-imbak sa isang arrayEntry[ ]
na tinatawag natable
; -
Ang array cell ay tinatawag na bucket at iniimbak ang unang elemento ng isang naka-link na listahan;
-
hashcode()
Ang object methodkey
ay ginagamit upang mahanap ang bucket ng class object na itoEntry
; -
Kung ang mga key ng dalawang object ay may parehong hash code, sila ay maiimbak sa parehong array bucket
table
; -
Ang pamamaraan
equals()
ng isang bagaykey
ay ginagamit upang kumpirmahin ang pagiging natatangi nito; -
Ang mga pamamaraan
equals()
athashcode()
bagayvalue
ay hindi ginagamit.
GO TO FULL VERSION