JavaRush /Blog Java /Random-MS /Bagaimanakah HashMap berfungsi di Java?
gnev
Tahap

Bagaimanakah HashMap berfungsi di Java?

Diterbitkan dalam kumpulan
Bagaimanakah HashMap berfungsi di Java?  - 1Selalunya dalam temu bual mereka bertanya soalan seperti " Bagaimana HashMap berfungsi di Jawa?" ”, “Apakah mekanisme dalaman bagaimana kaedah berfungsi getdalam putHashMap?”. 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 getjuga . putMari kita ambil contoh yang sangat mudah. Kami mempunyai kelas Country(bahasa Inggeris "negara"), kami akan menggunakan objek kelas Countrysebagai 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 hashcodedan 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: Bagaimanakah HashMap berfungsi di Java?  - 2Di ​​sini kita melihat perkara berikut:
  1. Terdapat tatasusunan Entry[]16 sel bernama table;

  2. Tatasusunan ini menyimpan objek kelas Entry. Kelas HashMapmempunyai kelas dalaman - Entry. Dan contoh kelas ini ialah pasangan nilai kunci. Mari kita lihat struktur kelas Entry:

  3. static class Entry implements Map.Entry
            {
                    final K key;
                    V value;
                    Entry next;
                    final int hash;
                    ...//продолжение codeа
            }
  4. Setiap kali kami cuba mencipta pasangan nilai kunci dalam peta cincang, objek kelas akan dibuat untuk pasangan itu Entrydan ia akan disimpan dalam jadual di atas Entry[]. 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 menggunakan hashcode(). Dan kod cincang ini digunakan untuk mengira nombor sel jadual Entry[];

  5. Sekarang jika anda melihat sel 10 jadual, anda akan melihat objek kelas Entrybernama HashMap$Entry;

  6. 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).
Begini cara kod cincang untuk pasangan nilai kunci kami akan dikira.
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: Bagaimanakah HashMap berfungsi di Java?  - 3Sekarang anda sudah mempunyai pemahaman tentang struktur peta cincang, mari kita beralih kepada kaedah putdan 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:
  1. Kami menyemak objek keyuntuk kesaksamaan null. Jika ya, maka objek keyakan disimpan di lokasi table[0]kerana kod cincang untuk nullsentiasa 0;

  2. keySeterusnya, kami memanggil kaedah objek hashcode(), yang akan mengira kod cincangnya. Kod cincang ini digunakan untuk menentukan sel tatasusunan di mana objek kelas akan disimpan Entry. Kadang-kadang ia berlaku bahawa fungsi ini hashcodetidak 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 ;

  3. indexFor(hash,table.length)digunakan untuk menentukan sel tertentu dalam tatasusunan tabledi mana objek kelas akan ditakrifkan untuk disimpan Entry;

  4. Seperti yang kita lihat dalam contoh kami, jika dua objek keymempunyai 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 Entryakan disimpan terus ke dalam sel ini;

    • jika sel ini sudah mengandungi beberapa objek, kemudian lelaran kepada elemen yang medannya nextsama dengan null. Selepas ini, objek kelas kami Entrymenjadi seterusnya dalam senarai;

    • bagaimana jika kita menambah objek yang sama keysekali lagi? Secara logiknya, ia sepatutnya menggantikan nilai lama. Ya, ia akan jadi begitu. Semasa lelaran, kekunci akan dibandingkan menggunakan kaedah equals()( key.equals(k)). Jika hasilnya benar, maka nilai lama akan digantikan dengan nilai objek semasa Entry.

Dapatkan:

Sekarang mari kita lihat aplikasi kaedah tersebut dapatkan
/**
  * 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 getsangat mudah. Apabila anda menghantar sebarang kunci kepada kaedah untuk mendapatkan nilai daripada peta cincang:
  1. Sebuah objek Ekey diuji untuk kesaksamaan null. Jika ya, maka nilai objek yang disimpan dalam sel akan dikembalikan table[0];

  2. Objek utama mempunyai kaedah yang dipanggil hashcode()yang mengira kod cincang;

  3. indexFor(hash,table.length)digunakan untuk menentukan sel tatasusunan tertentu tableuntuk mengambil objek kelas Entry;

  4. Selepas menerima nombor sel tatasusunan, tableia akan berulang melalui senarai dan membandingkan kekunci menggunakan kaedah equals(). Jika hasilnya benar, maka nilai objek akan dikembalikan Entry, jika tidak - null.

Perkara yang perlu diingat:

  • Kelas HashMapmempunyai kelas dalaman Entryyang menyimpan pasangan nilai kunci;

  • Objek kelas Entrydisimpan dalam tatasusunan Entry[ ]dipanggil table;

  • Sel tatasusunan dipanggil baldi dan menyimpan elemen pertama senarai terpaut;

  • Kaedah hashcode()objek keydigunakan untuk mencari baldi objek kelas ini Entry;

  • Jika kunci dua objek mempunyai kod cincang yang sama, ia akan disimpan dalam baldi tatasusunan yang sama table;

  • Kaedah equals()objek keydigunakan untuk mengesahkan keunikannya;

  • Kaedah equals()dan hashcode()objek valuetidak digunakan sama sekali.

Sumber
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION