中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

分析JDK的HashMap的原理

發布時間:2021-11-03 17:44:43 來源:億速云 閱讀:104 作者:iii 欄目:編程語言

這篇文章主要介紹“分析JDK的HashMap的原理”,在日常操作中,相信很多人在分析JDK的HashMap的原理問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”分析JDK的HashMap的原理”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1. 特性

我們可以用任何類作為HashMap的key,但是對于這些類應該有什么限制條件呢?且看下面的代碼:

public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
}
MaptestMap = new HashMap<>();
testMap.put(new Person("hello"), "world");
testMap.get(new Person("hello")); // ---> null

本是想取出具有相等字段值Person類的value,結果卻是null。對HashMap稍有了解的人看出來——Person類并沒有override hashcode方法,導致其繼承的是Object的hashcode(返回是其內存地址),兩次new出來的Person對象并不equals——這也是為什么在工程項目中常用不變類(如String、Integer等)做為HashMap的key的原因。那么,HashMap是如何利用hashcode給key做索引的呢?

2. 原理

首先,我們來看《Thinking in Java》中一個簡單HashMap的實現方案:

//: containers/SimpleHashMap.java
// A demonstration hashed Map.
import java.util.*;
import net.mindview.util.*;
public class SimpleHashMapextends AbstractMap{
  // Choose a prime number for the hash table size, to achieve a uniform distribution:
  static final int SIZE = 997;
  // You can't have a physical array of generics, but you can upcast to one:
  @SuppressWarnings("unchecked")
  LinkedList<1mapentry>[] buckets =
    new LinkedList[SIZE];
  public V put(K key, V value) {
    V oldValue = null;
    int index = Math.abs(key.hashCode()) % SIZE;
    if(buckets[index] == null)
      buckets[index] = new LinkedList<1mapentry>();
    LinkedList<1mapentry> bucket = buckets[index];
    MapEntrypair = new MapEntry(key, value);
    boolean found = false;
    ListIterator<1mapentry> it = bucket.listIterator();
    while(it.hasNext()) {
      MapEntryiPair = it.next();
      if(iPair.getKey().equals(key)) {
        oldValue = iPair.getValue();
        it.set(pair); // Replace old with new
        found = true;
        break;
      }
    }
    if(!found)
      buckets[index].add(pair);
    return oldValue;
  }
  public V get(Object key) {
    int index = Math.abs(key.hashCode()) % SIZE;
    if(buckets[index] == null) return null;
    for(MapEntryiPair : buckets[index])
      if(iPair.getKey().equals(key))
        return iPair.getValue();
    return null;
  }
  public Set<1map.entry> entrySet() {
    Set<1map.entry> set= new HashSet<1map.entry>();
    for(LinkedList<1mapentry> bucket : buckets) {
      if(bucket == null) continue;
      for(MapEntrympair : bucket)
        set.add(mpair);
    }
    return set;
  }
  public static void main(String[] args) {
    SimpleHashMapm =
      new SimpleHashMap();
    m.putAll(Countries.capitals(25));
    System.out.println(m);
    System.out.println(m.get("ERITREA"));
    System.out.println(m.entrySet());
  }
}

SimpleHashMap構造一個hash表來存儲key,hash函數是取模運算Math.abs(key.hashCode()) % SIZE,采用鏈表法解決hash沖突;buckets的每一個槽位對應存放具有相同(hash后)index值的Map.Entry,如下圖所示:
分析JDK的HashMap的原理
JDK的HashMap的實現原理與之相類似,其采用鏈地址的hash表table存儲Map.Entry:

/**
 * The table, resized as necessary. Length MUST Always be a power of two.
 */
transient Entry[] table = (Entry[]) EMPTY_TABLE;
static class Entryimplements Map.Entry{
    final K key;
    V value;
    Entrynext;
    int hash;
    …
}

Map.Entry的index是對key的hashcode進行hash后所得。當要get key對應的value時,則對key計算其index,然后在table中取出Map.Entry即可得到,具體參看代碼:

public V get(Object key) {
    if (key == null)
        return getForNullKey();
    Entryentry = getEntry(key);
    return null == entry ? null : entry.getValue();
}
final EntrygetEntry(Object key) {
    if (size == 0) {
        return null;
    }
    int hash = (key == null) ? 0 : hash(key);
    for (Entrye = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

可見,hashcode直接影響HashMap的hash函數的效率——好的hashcode會極大減少hash沖突,提高查詢性能。同時,這也解釋開篇提出的兩個問題:如果自定義的類做HashMap的key,則hashcode的計算應涵蓋構造函數的所有字段,否則有可能得到null。

到此,關于“分析JDK的HashMap的原理”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

三原县| 钟祥市| 道真| 双辽市| 佛冈县| 肃南| 邵东县| 会昌县| 乐清市| 道真| 新乡市| 榆社县| 修文县| 阿拉善右旗| 玉门市| 黄梅县| 安新县| 汶上县| 湛江市| 弥渡县| 武强县| 瓦房店市| 牟定县| 望谟县| 贺兰县| 墨竹工卡县| 江都市| 永顺县| 乐清市| 鹤峰县| 长岭县| 阿图什市| 黄大仙区| 黄浦区| 浑源县| 城固县| 昌都县| 资兴市| 平和县| 清水河县| 龙里县|