原始碼——手寫一個簡單的HashMap
阿新 • • 發佈:2018-12-23
定義:用於儲存Key-Value鍵值對集合,
儲存結構:線性連結串列(陣列+連結串列)。陣列:固定長度,索引效率高,增刪效率低-----連結串列:長度不固定,索引效率低,增刪效率高
雜湊值特點:同一物件呼叫多次hashcode()方法,必須返回相同的數值。(冪等)
如果兩個物件根據equals()方法比較是相等的,那麼兩個物件呼叫hashcode()方法返回的結果必須相等;
if(a==b) a.hashcode()==b.hashcode()
如果兩個物件的equals()方法比較是不相等的,那麼兩個物件呼叫hashcode()方法返回的結果不一定不相等
hash演算法實現:取模,求與,線性探測,其他
public interface Map<K,V> {
//向hashMap中插入值
public V put(K k,V v);
//根據key獲取hashMap中的值
public V get(K k);
//獲得集合中元素的個數
public int size();
//獲取集合中,鍵值對的物件
interface Entry<K,V>{
K getKey();
V getValue();
V setValue(V v);
}
}
package HashMap; public class HashMap<K, V> implements Map<K, V> { //資料儲存的結構==>陣列+連結串列 Node<K,V>[] array=null; //陣列/雜湊桶的長度 private static int defaultLength=16; //載入因子/擴容因子 private static double factor=0.75D; //集合中的元素個數 private int size; //測試列印函式 public void print() { System.out.println("==============================="); if(array!=null) { Node<K, V> node=null; for (int i = 0; i < array.length; i++) { node=array[i]; System.out.print("下標["+i+"]"); //遍歷連結串列 while(node!=null) { System.out.print("["+node.getKey()+":"+node.getValue()+"]"); if(node.next!=null) { node=node.next; }else { //到尾部元素 node=null; } } System.out.println(); } } } //put元素方法 @Override public V put(K k, V v) { //1.懶載入機制,使用的時候進行分配 if(array==null) { array=new Node[defaultLength]; } //2.通過hash演算法,計算出具體插入的位置 int index=position(k,defaultLength); //擴容。判斷是否需要擴容 //擴容的準則,元素的個數 大於 桶的尺寸*載入因子 if(size > defaultLength*factor) { resize(); } //3.放入要插入的元素 Node<K, V> node=array[index]; if(node==null) { array[index]=new Node<K,V>(k,v,null); size++; }else { if(k.equals(node.getKey()) || k==node.getKey()) { return node.setValue(v); }else { array[index]=new Node<K,V>(k,v,node); size++; } } return null; } //擴容,並且重新排列元素 private void resize() { //翻倍擴容 //1.建立新的array臨時變數,相當於defaultlength*2 Node<K, V>[] temp=new Node[defaultLength << 1]; //2.重新計算雜湊值,插入到新的array中去。 code=key % defaultLength ==> code=key % defaultLength*2 Node<K, V> node=null; for (int i = 0; i < array.length; i++) { node=array[i]; while(node!=null) { //重新雜湊 int index=position(node.getKey(),temp.length); //插入頭部 Node<K, V> next = node.next; //3 node.next=temp[index]; //1 temp[index]=node; //2 node=next; } } //3.替換掉老array array=temp; defaultLength=temp.length; temp=null; } private int position(K k,int length) { int code=k.hashCode(); //取模演算法 return code % (length-1); //求與演算法 //return code & (defaultLength-1); } @Override public V get(K k) { if(array!=null) { int index=position(k,defaultLength); Node<K, V> node=array[index]; //遍歷連結串列 while(node!=null) { //如果key值相同返回value if(node.getKey()==k) return node.getValue(); else //如果key值不同則調到下一個元素 node=node.next; } } return null; } @Override public int size() { return size; } static class Node<K,V> implements Entry<K,V>{ K key; V value; Node<K,V> next; public Node(K key, V value, Node<K, V> next) { super(); this.key = key; this.value = value; this.next = next; } @Override public K getKey() { return this.key; } @Override public V getValue() { return this.value; } @Override public V setValue(V v) { V oldValue=this.value; this.value=v; return oldValue; } } }
public class Test { public static void main(String[] args) { HashMap<String, String> map=new HashMap<String, String>(); map.put("001號", "001"); map.put("002號", "002"); map.put("003號", "003"); map.put("004號", "004"); map.put("005號", "005"); map.put("006號", "006"); map.put("007號", "007"); map.put("008號", "008"); map.put("009號", "009"); map.put("010號", "010"); map.put("011號", "011"); map.print(); System.out.println("========>"+map.get("009號")); } }