亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Java源碼角度分析HashMap用法

2024-07-13 10:15:56
字體:
來源:轉載
供稿:網友

—HashMap—

優點:超級快速的查詢速度,時間復雜度可以達到O(1)的數據結構非HashMap莫屬。動態的可變長存儲數據(相對于數組而言)。

缺點:需要額外計算一次hash值,如果處理不當會占用額外的空間。

—HashMap如何使用—

平時我們使用hashmap如下

Map<Integer,String> maps=new HashMap<Integer,String>();   maps.put(1, "a");   maps.put(2, "b");

上面代碼新建了一個HashMap并且插入了兩個數據,這里不接受基本數據類型來做K,V

如果這么寫的話,就會出問題了:

Map<int,double> maps=new HashMap<int,double>();

我們為什么要這樣使用呢?請看源碼:

public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable 

這是HashMap實現類的定義。

—HashMap是一個動態變長的數據結構—

在使用HashMap的時候,為了提高執行效率,我們往往會設置HashMap初始化容量:

Map<String,String> rm=new HashMap<String,String>(2)

或者使用guava的工具類Maps,可以很方便的創建一個集合,并且,帶上合適的大小初始化值。

Map<String, Object> map = Maps.newHashMapWithExpectedSize(7);

那么為什么要這樣使用呢?我們來看他們的源碼構造函數。

未帶參的構造函數:

public HashMap() {       this.loadFactor = DEFAULT_LOAD_FACTOR;       threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);       table = new Entry[DEFAULT_INITIAL_CAPACITY];       init();     } 

public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
table = new Entry[DEFAULT_INITIAL_CAPACITY];
init();
}

/**    * Constructs an empty <tt>HashMap</tt> with the specified initial    * capacity and the default load factor (0.75).    *    * @param initialCapacity the initial capacity.    * @throws IllegalArgumentException if the initial capacity is negative.    */   public HashMap(int initialCapacity) {     this(initialCapacity, DEFAULT_LOAD_FACTOR);   }

名詞解釋:

DEFAULT_LOAD_FACTOR  //默認加載因子,如果不制定的話是0.75  DEFAULT_INITIAL_CAPACITY //默認初始化容量,默認是16  threshold //閾(yu)值 根據加載因子和初始化容量計算得出 ,<span style="color: rgb(54, 46, 43); font-family: "microsoft yahei";">threshold表示當HashMap的size大于threshold時會執行resize操作。

因此我們知道了,如果我們調用無參數的構造方法的話,我們將得到一個16容量的數組。

所以問題就來了:如果初始容量不夠怎么辦?

數組是定長的,如何用一個定長的數據來表示一個不定長的數據呢,答案就是找一個更長的,但是在resize的時候是很降低效率的。所以我們建議HashMap的初始化的時候要給一個靠譜的容量大小。

—HashMap的Put方法—

public V put(K key, V value) {      if (key == null) //鍵為空的情況,HashMap和HashTable的一個區別        return putForNullKey(value);      int hash = hash(key.hashCode()); //根據鍵的hashCode算出hash值      int i = indexFor(hash, table.length); //根據hash值算出究竟該放入哪個數組下標中      for (Entry<K,V> e = table[i]; e != null; e = e.next) {//整個for循環實現了如果存在K那么就替換V        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;    }

如果插入的數據超過現有容量就會執行

addEntry(hash, key, value, i);
void addEntry(int hash, K key, V value, int bucketIndex) {   Entry<K,V> e = table[bucketIndex];       table[bucketIndex] = new Entry<K,V>(hash, key, value, e);       if (size++ >= threshold)        <span style="color:#ff0000;"><strong> resize(2 * table.length);}

這里顯示了如果當前 size++ >threshold 的話那么就會擴展當前的size的兩倍,執行resize(2*table.length),那么他們是如何擴展的呢?

void resize(int newCapacity) {       Entry[] oldTable = table;       int oldCapacity = oldTable.length;       if (oldCapacity == MAXIMUM_CAPACITY) {         threshold = Integer.MAX_VALUE;         return;       }         Entry[] newTable = new Entry[newCapacity]; <span style="color: rgb(51, 51, 51); font-family: Arial;">new 一個新的數組,</span>     <strong> <span style="color:#ff0000;">transfer(newTable);</span> </strong> //將就數組轉移到新的數組中     table = newTable;       threshold = (int)(newCapacity * loadFactor);  //重新計算容量   }

對于轉移數組transfer是如何轉移的呢?

void transfer(Entry[] newTable) {       Entry[] src = table;       int newCapacity = newTable.length;       for (int j = 0; j < src.length; j++) {         Entry<K,V> e = src[j];         if (e != null) {           src[j] = null;           do {             Entry<K,V> next = e.next;             int i = <strong><span style="color:#ff0000;">indexFor(e.hash, newCapacity);  //根據hash值個容量重新計算下標</span></strong>           e.next = newTable[i];             newTable[i] = e;             e = next;           } while (e != null);         }       }     } 

—hashmap擴容額外執行次數—

因此如果我們要添加一個1000個元素的hashMap,如果我們用默認值那么我么需要額外的計算多少次呢

當大于16*0.75=12的時候,需要從新計算12次

當大于16*2*0.75=24的時候,需要額外計算24次

……

當大于16*n*0.75=768的時候,需要額外計算768次

所以我們總共在擴充過程中額外計算12+24+48+……+768次

因此強力建議我們在項目中如果知道范圍的情況下,我們應該手動指定初始大小像這樣:

Map<Integer,String> maps=new HashMap<Integer,String>(1000);

總結:這就是為什么當hashmap使用過程中如果超出 初始容量后他的執行效率嚴重下降的原因。

以上就是本文關于Java源碼角度分析HashMap用法的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美成人网| 国内久久久精品| 日韩av中文字幕在线免费观看| 精品爽片免费看久久| 国产精品老牛影院在线观看| 国产91av在线| 成人午夜激情免费视频| 久久久久久国产精品| 亚洲精品狠狠操| 欧美日韩精品在线播放| 亚洲午夜国产成人av电影男同| 国产色综合天天综合网| 欧美伦理91i| 91免费精品视频| 91系列在线观看| 国产精品丝袜久久久久久高清| 久久在线免费观看视频| 国产精品视频久久久| 欧美精品久久久久久久久久| 色偷偷噜噜噜亚洲男人的天堂| 在线观看欧美www| 久久久欧美一区二区| 久久久国产一区二区三区| 精品女同一区二区三区在线播放| 亚洲午夜性刺激影院| 国产91精品久久久久久久| 国产欧美久久久久久| 日韩成人av网址| 奇门遁甲1982国语版免费观看高清| 亚洲乱亚洲乱妇无码| 57pao成人永久免费视频| 久久免费少妇高潮久久精品99| 国产精品中文字幕在线| 国产精品视频网| 亚洲人午夜精品| 97在线看福利| 亚洲欧美另类自拍| 日韩成人性视频| 欧美激情亚洲视频| 国产精品久久久久aaaa九色| 欧美日韩ab片| 国产va免费精品高清在线观看| 亚洲a在线播放| 国产亚洲精品美女| 亚洲自拍偷拍网址| 欧美在线视频免费观看| 亚洲人午夜精品免费| 日韩成人在线电影网| 欧美日韩亚洲视频一区| 国产一区二区三区在线观看网站| 亚洲欧洲一区二区三区在线观看| 色七七影院综合| 在线电影欧美日韩一区二区私密| 日韩电视剧在线观看免费网站| 国产精品xxx视频| 国产一区二区三区在线免费观看| 午夜精品久久久久久久99热| 国产精品亚洲аv天堂网| 欧美在线激情视频| 国模吧一区二区三区| 亚洲欧美一区二区激情| 91精品成人久久| 国产激情999| 欧美性猛交xxxx| 亚洲大胆人体在线| 日韩理论片久久| 国产精品久久久久免费a∨大胸| 国产精品一二三视频| 亚洲午夜久久久影院| 亚洲天堂第一页| 亚洲成人动漫在线播放| 亚洲欧美激情精品一区二区| 国产精品久久久久久av福利软件| 亚洲欧美激情精品一区二区| 欧美午夜精品久久久久久人妖| 色视频www在线播放国产成人| 国产精品久久不能| 久久天天躁狠狠躁夜夜躁2014| 日韩av网址在线| 欧美日韩国产成人在线| 久久国产精品久久国产精品| 国产精品扒开腿做爽爽爽视频| 91久久综合亚洲鲁鲁五月天| 91精品免费久久久久久久久| 韩国欧美亚洲国产| 一区二区三区亚洲| 色多多国产成人永久免费网站| 久久午夜a级毛片| 欧美国产日韩在线| 免费97视频在线精品国自产拍| 欧美电影电视剧在线观看| 欧美丰满少妇xxxxx做受| 久久亚洲精品一区二区| 青青草一区二区| 欧美www在线| 国产色婷婷国产综合在线理论片a| 色av中文字幕一区| 97精品欧美一区二区三区| 欧美主播福利视频| 久久视频免费观看| 亚洲国产精品va在线看黑人| 欧美在线亚洲在线| 欧美亚洲另类激情另类| 色在人av网站天堂精品| 亚洲免费视频网站| 国产日韩换脸av一区在线观看| 少妇av一区二区三区| 国产91九色视频| 成人国内精品久久久久一区| 久久精品一本久久99精品| 亚洲最大av网| 久久久国产视频| 亚洲最大成人在线| 日韩精品中文字幕有码专区| 日韩资源在线观看| 国产mv免费观看入口亚洲| 国产精品白丝jk喷水视频一区| 日韩欧美一区视频| 日韩精品福利在线| 亚洲xxxx18| 精品美女国产在线| 97精品视频在线播放| 久久久伊人日本| 91精品在线国产| 亚洲视频一区二区| 欧美在线激情网| 亚洲欧洲xxxx| 国产一区深夜福利| 欧美亚洲激情视频| 欧美小视频在线观看| 91精品国产一区| 久久久亚洲精品视频| 国产视频在线观看一区二区| 国产精品亚洲美女av网站| 国产精品福利在线观看网址| 欧美午夜精品在线| 亚洲免费高清视频| 亚洲天堂男人天堂女人天堂| 国产精品黄色av| 国产精品美女主播在线观看纯欲| 久久久精品999| 欧美性xxxxx| 成人久久久久爱| 国产精品久久久久久久久久99| 亚洲欧美国内爽妇网| 91免费视频网站| 国产精品美女免费看| 国产精品对白刺激| 国产精品狼人色视频一区| 欧美另类在线播放| 热99在线视频| 欧美性猛交xxxx免费看久久久| 萌白酱国产一区二区| 亚洲97在线观看| 亚洲欧洲在线看| 91在线观看免费| 久久综合久久八八| 狠狠躁夜夜躁久久躁别揉| 亚洲精品v天堂中文字幕| 欧美专区第一页| www.日韩不卡电影av| 深夜福利亚洲导航| 亚洲最大的免费| 综合网中文字幕|