1. 程式人生 > >《java編程思想》:散列的原理

《java編程思想》:散列的原理

col break fin nal [] str lean nbsp lin

以實現一個簡單的HashMap為例,詳細講解在code之中。

簡單解釋散列原理:

1.map中內建固定大小數組,但是數組並不保存key值本身,而是保存標識key的信息

2.通過key生成數組角標,對應位置存放LinkedList,list中存放的是鍵值對

3.如此,無論放入多少個鍵值對,數組大小都不必改變,當key值生成的角標值重復時,獲取對應位置的list,向list中添加鍵值對即可

4.當調用get()方法時,只需遍歷對應角標位置的list,而不用遍歷所有的鍵值對信息,所以加快了查詢速度。

5.註意,get()和put()中使用的計算散列值,也就是數組角標的公式一定要一致,保證計算所得的角標一致

/**
 * Created by Don9 on 2017/
 */
public class MyHashMap<K,V> extends AbstractMap<K,V>{
    /* 1.自定義數組大小 */
    static final int SIZE = 999;
    /* 2.創建內部數組,數組存放的是LinkedList,而list中存放的是想要存放的鍵值對 */
    LinkedList<MyEntry<K,V>>[] buckets = new LinkedList[999];
    /* 3.put方法,此方法返回key對應的曾經的oldValue 
*/ public V put(K key,V value){ /* 4.先定義一個返回值 */ V oldValue = null; /* 5.根據key計算出一個散列值,用於當作內置數組的下角標( 此公式不固定,是自定義的,但是要保證結果穩定不變,同時不能大於數組size) */ int index = Math.abs(key.hashCode()) % SIZE; /* 6.當index位置為空時,填充新的list */ if(buckets[index]==null){ buckets[index]
= new LinkedList<MyEntry<K,V>>(); } /* 7.獲取index位置的list */ LinkedList<MyEntry<K, V>> bucket = buckets[index]; /* 8.MyEntry是自定義的Entry實現類,用於保存鍵值對,這個類也可以自定義,只要實現接口Entry即可, 新建entry保存傳入的鍵值對 */ MyEntry<K, V> newMe = new MyEntry<K, V>(key,value); /* 9.定義一個found標記,用於記錄是否替換完畢 */ boolean found = false; ListIterator<MyEntry<K, V>> it = bucket.listIterator(); /* 10.遍歷當前位置的list */ while(it.hasNext()){ MyEntry<K, V> oldMe = it.next(); /* 11.list中已經存在了當前key */ if(oldMe.getKey().equals(key)){ /* 12.獲得oldValue值,用於返回 */ oldValue = oldMe.getValue(); /* 13.用新的entry替換老的 */ it.set(newMe); /* 14.標記改為true,說明替換完畢 */ found = true; /* 15.跳出 */ break; } } /* 16.如果未替換完畢,也就是說key值在之前的list中不存在 */ if(!found){ /* 17.添加新的entry到list中 */ bucket.add(newMe); } /* 18.返回oldValue */ return oldValue; } /* 19.定義get查找方法 */ public V get(Object key){ /* 20.生成散列值,也就是數組角標,此處一定要和put方法中生成方式一致,保證相同的key生成相同的位置 */ int index = Math.abs(key.hashCode()) % SIZE; /* 21.index位置為null,不存在key,返回null */ if(buckets[index]==null){ return null; } /* 22.index位置不為null,遍歷查詢,返回value */ for(MyEntry<K,V> me:buckets[index]){ if(me.getKey().equals(key)){ return me.getValue(); } } return null; } @Override public Set<Entry<K, V>> entrySet() { return null; } }

《java編程思想》:散列的原理