在Java
中,有一種並且咱們使用很頻繁的數據結構,叫作HashMap
,其實準確的來講,這是散列表
的一種衝突解決的實現,那麼什麼是散列表
呢?這個概念在網上能夠找到不少專業的回答,這裏咱們就舉一個很簡單的例子來講明一下什麼是散列表
。算法
首先咱們要明確的一點,就是散列表確定是用來存取東西的,那麼若是咱們要把西瓜
,蘋果
,草莓
這三種東西按照重量
存到某個地方,方便咱們後面再拿來使用,這個該如何操做呢?首先咱們能夠拿一個彈簧,而後使用這個彈簧將這些東西按照重量彈出去,由於重量的不一樣,將會落在不一樣的區域,這樣就將這些東西「保存」了起來。若是咱們後面要使用這些東西的時候,只須要按照重量再去使用一次彈簧就能夠了,這樣就能找到咱們所須要找的。數組
這裏咱們再明確幾個概念,這個例子中的幾種東西,就是咱們要存放的數據
,彈簧指的是hash算法
,由於這些數據的存放是無序的,因此這些概念綜合起來看,稱這種形式爲散列表
。數據結構
還有一個問題,就是若是在這個散列表中有兩個數據經過hash
算法落到了同一個區域,那麼在這裏就稱之爲衝突
,或者叫hash
衝突,在散列表中,解決衝突的方式有線性探測法
,平方探測法
,鏈式地址法
。。。不少種方式,在這裏就不討論每一種解決方式的利弊,咱們只是對於Java
中的HashMap
做爲研究。性能
若是看過HashMap
源碼的朋友就會知道,在Java
中HashMap
是基於鏈式地址法來實現的,固然也有不少朋友可能不太喜歡看源碼,好的,那麼咱們就按照HashMap
來動手寫一個簡單的實現。this
咱們先定義一個節點類。設計
public class Entry { private Integer key; private String value; private Entry next; public Entry(Integer key, String value, Entry next){ this.key = key; this.value = value; this.next = next; } }
而後咱們在定義一個CopyHashMap類。code
public class CopyHashMap { private final static int DEFAULT_CAPCITY = 11; private Entry[] arrEntry; public CopyHashMap(){ arrEntry = new Entry[DEFAULT_CAPCITY]; } public CopyHashMap(int size){ arrEntry = new Entry[size]; } private int hash(int key){ return key % DEFAULT_CAPCITY; } public String get(int key){ int h = hash(key); Entry entry = arrEntry[h]; for (Entry e = entry; e != null; e = e.getNext()){ if (e.getKey().equals(key)){ return e.getValue(); } } return null; } public void put(int key, String value){ int h = hash(key); Entry entry = arrEntry[h]; for (Entry e = entry; e != null; e = e.getNext()){ if (e.getKey().equals(key)){ e.setValue(value); } } arrEntry[h] = new Entry(key, value, arrEntry[h]); } }
這裏只是簡單的寫了一個get
和put
方法,代碼很簡單,看一看應該都能明白,能夠看到其底層實現仍是依賴於一個數組,這裏有一個hash
的方法,這個就是咱們剛開始例子中的彈簧,對於每個key
都要去計算對應的hash
值是多少,而後才能肯定存放在數組中的哪一個位置,因此可以看出,散列表
中的hash
算法的設計是很是重要的。rem
這段代碼中還有一些東西沒有作,好比remove
方法,還有rehash
方法,若是你有興趣,那麼能夠動手實現一下這兩個方法,rehash
的過程在這裏順便提一下,簡單的說就是若是存儲列表不夠用的狀況下,hash
表會擴容,而後將裏面的數據從新hash
一次,固然這個rehash
會提早開始進行的,因此這裏咱們能夠觀察到一個現象就是若是散列表rehash
一次,對程序的性能影響仍是比較大的,對了,在JDK8
中,HashMap
也作了一些改進,鏈式存儲的時候,在其長度達到某一個定值,後面的存儲方式會轉爲紅黑樹的形式,有興趣的話能夠看一下源碼。get
HashMap
在Java
中的使用很頻繁,不少人應該都懂其原理,可能也有不少人不太明白,但願這篇文章能讓你們初窺HashMap
的門道,更深刻的研究就只能你們本身探索了。源碼