JavaRush /Java Blog /Random-TL /Paano gumagana ang HashMap sa Java?
gnev
Antas

Paano gumagana ang HashMap sa Java?

Nai-publish sa grupo
Paano gumagana ang HashMap sa Java?  - 1Kadalasan sa mga panayam ay nagtatanong sila tulad ng " Paano gumagana ang HashMap sa Java?" ”, “Ano ang panloob na mekanismo kung paano gumagana ang mga pamamaraan getsa putHashMap?”. 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 getrin kung paano gumagana ang mga pamamaraan putsa Java . Kumuha tayo ng isang napakasimpleng halimbawa. Mayroon kaming klase Country(Ingles na "bansa"), gagamitin namin ang class object Countrybilang 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 hashcodeat 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: Paano gumagana ang HashMap sa Java?  - 2Dito makikita natin ang sumusunod:
  1. Mayroong isang hanay Entry[]ng 16 na mga cell na pinangalanang table;

  2. Ang array na ito ay nag - iimbak ng mga bagay ng klase Entry. Ang klase HashMapay may panloob na klase - Entry. At ang mga instance ng klase na ito ay key-value pairs. Tingnan natin ang istraktura ng klase Entry:

  3. static class Entry implements Map.Entry
            {
                    final K key;
                    V value;
                    Entry next;
                    final int hash;
                    ...//продолжение codeа
            }
  4. Sa tuwing susubukan naming gumawa ng key-value pair sa isang hash map, gagawa ng class object para sa pares na iyon Entryat ito ay maiimbak sa talahanayan sa itaas Entry[]. 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 ang hashcode(). At ang hash code na ito ay ginagamit upang kalkulahin ang numero ng cell ng talahanayan Entry[];

  5. Ngayon, kung titingnan mo ang cell 10 ng talahanayan, makikita mo ang isang object ng klase Entryna pinangalanang HashMap$Entry;

  6. 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).
Narito kung paano kakalkulahin ang hash code para sa aming mga key-value pairs.
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: Paano gumagana ang HashMap sa Java?  - 3Ngayon na mayroon ka nang pag-unawa tungkol sa istraktura ng mga hash na mapa, lumipat tayo sa putat 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:
  1. Sinusuri namin ang bagay keypara sa pagkakapantay-pantay null. Kung gayon, ang bagay keyay maiimbak sa lokasyon table[0]dahil ang hash code para sa nullay palaging 0;

  2. Susunod, tinatawag namin ang object's keymethod hashcode(), na kakalkulahin ang hash code nito. Ang hash code na ito ay ginagamit upang matukoy ang array cell kung saan iimbak ang class object Entry. Minsan nangyayari na ang function na ito hashcodeay 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 ;

  3. indexFor(hash,table.length)ginagamit upang tukuyin ang isang tiyak na cell sa array tablekung saan ang isang bagay ng klase ay tutukuyin upang maiimbak Entry;

  4. Tulad ng nakita natin sa aming halimbawa, kung ang dalawang bagay keyay 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 Entryay 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 nextkatumbas ng null. Pagkatapos nito, ang aming class object Entryay magiging susunod sa listahan;

    • paano kung idagdag natin keymuli ang parehong bagay? Logically, dapat nitong palitan ang lumang halaga. Oo, magiging gayon. Sa panahon ng pag-ulit, ihahambing ang mga susi gamit ang equals()( key.equals(k)) na pamamaraan. Kung totoo ang resulta, ang lumang halaga ay papalitan ng halaga ng kasalukuyang bagay Entry.

Kunin:

Ngayon tingnan natin ang aplikasyon ng pamamaraan makuha
/**
  * 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 getnapakasimple. Kapag nagpasa ka ng anumang key sa isang paraan para makakuha ng value mula sa hash map:
  1. Isang bagay Ang Ekey ay nasubok para sa pagkakapantay-pantay null. Kung gayon, ang halaga ng bagay na nakaimbak sa cell ay ibabalik table[0];

  2. Ang pangunahing bagay ay may tinatawag na pamamaraan hashcode()na kinakalkula ang hash code;

  3. indexFor(hash,table.length)ginagamit upang matukoy ang isang tiyak na array cell tablekung saan kukuha ng isang bagay ng klase Entry;

  4. Pagkatapos matanggap ang array cell number, tableito ay umulit sa listahan at ihahambing ang mga key gamit ang pamamaraan equals(). Kung totoo ang resulta, ibabalik ang halaga ng bagay Entry, kung hindi - null.

Bagay na dapat alalahanin:

  • Ang klase HashMapay may panloob na klase Entryna nag-iimbak ng mga pares ng key-value;

  • Ang mga bagay ng klase Entryay naka-imbak sa isang array Entry[ ]na tinatawag na table;

  • Ang array cell ay tinatawag na bucket at iniimbak ang unang elemento ng isang naka-link na listahan;

  • hashcode()Ang object method keyay ginagamit upang mahanap ang bucket ng class object na ito Entry;

  • 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 bagay keyay ginagamit upang kumpirmahin ang pagiging natatangi nito;

  • Ang mga pamamaraan equals()at hashcode()bagay valueay hindi ginagamit.

Pinagmulan
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION