JavaRush /Блоги Java /Random-TG /HashMap дар Java чӣ гуна кор мекунад?
gnev
Сатҳи

HashMap дар Java чӣ гуна кор мекунад?

Дар гурӯҳ нашр шудааст
HashMap дар Java чӣ гуна кор мекунад?  - 1Бисёр вақт дар мусоҳибаҳо онҳо саволҳое медиҳанд, ки " HashMap дар Java чӣ гуна кор мекунад?" get”, "Механизми дохorи кор кардани усулҳо дар HashMap чист put?". Дар ин ҷо ман кӯшиш мекунам, ки функсияи дохorро бо як мисоли оддӣ шарҳ диҳам. Бидуни ба назарияи аз ҳад зиёд ворид шудан, мо бо як мисол оғоз мекунем, то шумо беҳтар фаҳмед ва сипас бубинед, ки усулҳо дар Java getниз чӣ гуна кор мекунанд. putБиёед як мисоли хеле соддаро гирем. Мо синф дорем Country(англисӣ "country"), мо an objectи синфро Countryҳамчун калид ва номи пойтахти ин кишварро ҳамчун арзиш истифода хоҳем кард. Дар зер намунае оварда шудааст, ки ба мо фаҳмем, ки чӣ гуна ҷуфти калид-арзиш дар харитаи ҳаш нигоҳ дошта мешавад.

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;
 }
}
Агар шумо хоҳед, ки дар бораи усулҳо hashcodeва баробарҳо бештар фаҳмед ва омӯзед, шумо метавонед ин пайвандро пайгирӣ кунед .

2. HashMapStructure.java (синфи асосӣ)

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);
            }
        }
}
Акнун нуқтаи танаффусро ба сатри 23 таъин кунед ва иҷро кунед -> debug as-> барномаи java (қадди тарҷумон - барои Eclipse эътибор дорад). Барнома иҷроишро дар сатри 23 қатъ мекунад, пас аз он тугмаи рости мушро дар countryCapitalMap клик кунед ва тамошоро интихоб кунед . Шумо чунин ҷадвалро хоҳед дид: HashMap дар Java чӣ гуна кор мекунад?  - 2Дар ин ҷо мо инҳоро мебинем:
  1. Массиви Entry[]аз 16 ячейка мавҷуд аст, ки бо номи table;

  2. Ин массив an objectҳои синфро нигоҳ медорад Entry. Синф синфи HashMapдохorро дорад - Entry. Ва мисолҳои ин синф ҷуфтҳои калид-арзиш мебошанд. Биёед ба сохтори синф назар андозем Entry:

  3. static class Entry implements Map.Entry
            {
                    final K key;
                    V value;
                    Entry next;
                    final int hash;
                    ...//продолжение codeа
            }
  4. Ҳар дафъае, ки мо кӯшиш мекунем, ки ҷуфти калид-арзишро дар харитаи хэш эҷод кунем, барои он ҷуфт an objectи синфӣ эҷод карда мешавад Entryва он дар ҷадвали боло нигоҳ дошта мешавад Entry[]. Ва акнун шумо бояд дар ҳайрат бошед, ки ин an object маҳз дар куҷо (дар кадом ячейка) навишта мешавад. Барои калид дар ҷуфти калид-арзиш, codeи хэш бо истифода аз hashcode(). Ва ин рамзи hash барои ҳисоб кардани рақами чашмаки ҷадвал истифода мешавад Entry[];

  5. Акнун, агар шумо ба чашмаки 10-и ҷадвал назар кунед, шумо an objectи синфро хоҳед дид, Entryки бо номи HashMap$Entry;

  6. Мо 4 ҷуфти калид-арзишро илова кардем, аммо дар массив ҳамагӣ 2 адад ҳаст!!! Сабаб дар он аст, ки агар 2 an object як codeи хэш дошта бошанд, пас онҳо дар як чашмак нигоҳ дошта мешаванд. Аммо чи тавр? Объектҳо ҳамчун рӯйхати алоқаманд нигоҳ дошта мешаванд ( LinkedList).
Ин аст, ки чӣ тавр 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 имеет четное количество букв.
Тасвири зерин идеяи рӯйхати алоқамандро шарҳ медиҳад: HashMap дар Java чӣ гуна кор мекунад?  - 3Акнун, ки шумо аллакай дар бораи сохтори харитаҳои хэш фаҳмед, биёед ба усулҳо putва усулҳо гузарем get.

Гузоштан:

Биёед бубинем, ки ин усул чӣ гуна истифода мешавад:
/**
  * Метод связывает указанное 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;
 }
Акнун биёед кӯшиш кунем, ки ин codeро зина ба зина фаҳмем:
  1. Мо an objectро keyбарои баробарӣ тафтиш мекунем null. Агар ин тавр бошад, он гоҳ an object keyдар макон нигоҳ дошта мешавад table[0], зеро рамзи хэш барои nullҳамеша 0 аст;

  2. keyБаъдан, мо усули an objectро меномем hashcode(), ки рамзи хэш-и худро ҳисоб мекунад. Ин рамзи хэш барои муайян кардани ячейкаи массив, ки дар он an objectи синф нигоҳ дошта мешавад, истифода мешавад Entry. Баъзан чунин мешавад, ки ин функсия hashcodeчандон моҳирона навишта нашудааст, аз ин рӯ, таҳиягарони JDK функсияи дигарро эҷод карданд - hash(), ки рамзи хэш-и қаблан ҳисобшударо ҳамчун аргумент мегирад. Агар шумо хоҳед, ки дар бораи ин функсия муфассалтар хонед, шумо метавонед ба истиноди пайравӣ кунед ;

  3. indexFor(hash,table.length)барои муайян кардани ячейкаи мушаххас дар массив, tableки дар он an objectи синф барои нигоҳдорӣ муайян карда мешавад, истифода мешавад Entry;

  4. Тавре ки мо дар мисоли мо дидем, агар ду an object keyяк рамзи хэш дошта бошанд (ин вазъият ҳамчун бархӯрд маълум аст), он гоҳ онҳо дар шакли рӯйхати алоқаманд нигоҳ дошта мешаванд. Аз ин рӯ, дар ин марҳила мо рӯйхати худро такрор мекунем:

    • агар ячейкаи нав ҳисобшуда холӣ бошад, an objectи синф Entryбевосита дар ин ячейка захира карда мешавад;

    • агар ин ячейка аллакай ягон an object дошта бошад, он гоҳ ба элементе, ки майдони он nextба null. Пас аз ин, an objectи синфи мо Entryдар рӯйхат навбатӣ мешавад;

    • keyагар боз ҳамон an objectро илова кунем-чӣ ? Мантиқан, он бояд арзиши кӯҳнаро иваз кунад. Бале, чунин мешавад. Ҳангоми такрор, калидҳо бо усули equals()( key.equals(k)) муқоиса карда мешаванд. Агар натиҷа дуруст бошад, он гоҳ арзиши кӯҳна бо арзиши an objectи ҷорӣ иваз карда мешавад Entry.

Гирифтан:

Акнун биёед ба истифодаи усул назар андозем ба даст
/**
  * 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;
 }
Акнун, ки шумо фаҳмед, ки чӣ тавр усули гузоштан дар hasshmaps кор мекунад, фаҳмед, ки чӣ тавр усули гузоштан кор мекунад, getхеле содда аст. Вақте ки шумо ягон калидро ба усул барои гирифтани арзиш аз харитаи hash интиқол медиҳед:
  1. Объект Экей барои баробарӣ санҷида мешавад null. Агар ин тавр бошад, он гоҳ арзиши an objectи дар чашмак нигоҳ дошташуда баргардонида мешавад table[0];

  2. Объекти калидӣ дорои усуле мебошад, hashcode()ки рамзи ҳашро ҳисоб мекунад;

  3. indexFor(hash,table.length)барои муайян кардани ячейкаи массиви мушаххас, tableки аз он an objectи синф гирифта мешавад, истифода мешавад Entry;

  4. Пас аз гирифтани рақами ячейкаи массив, tableон рӯйхатро такрор мекунад ва калидҳоро бо усули equals(). Агар натиҷа дуруст бошад, он гоҳ арзиши an object баргардонида мешавад Entry, дар акси ҳол - null.

Чизҳое, ки бояд дар хотир дошта бошанд:

  • Синф HashMapдорои синфи ботинӣ мебошад Entry, ки ҷуфтҳои калид-арзишро нигоҳ медорад;

  • Объектҳои синф Entryдар массив Entry[ ]бо номи table;

  • Ячейкаи массив сатил номида мешавад ва элементи якуми рӯйхати алоқамандро нигоҳ медорад;

  • Усули hashcode()an object keyбарои дарёфти сатor ин an objectи синф истифода мешавад Entry;

  • Агар калидҳои ду an object як codeи хэш дошта бошанд, онҳо дар як сатил массив нигоҳ дошта мешаванд table;

  • Усули equals()an object keyбарои тасдиқи беназири он истифода мешавад;

  • Усулхо equals()ва hashcode()an objectхо valueтамоман истифода намешаванд.

Сарчашма
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION