03.Java數據結構與算法之~HashMap(簡易版)

03.Java數據結構與算法之~HashMap

HashMap的原理

       底層結構是哈希表,採用了順序表+鏈表結合結構;同一個鏈表的上所有元素的存儲地址都是相同的,是發生衝突的元素

       鏈表上每個節點的就是一個Entry,字段包括四部分

       哈希碼可能不相同,存儲地址相同。

哈希表的優點

       添加快、查詢快(通過計算得到存儲位置,不是通過比較) 無序 (key)唯一關鍵參數

        默認主數組長度16; 默認裝填因子0.75。 每次主數組擴容爲原來的2倍 JDK8,當鏈表長度大於8,鏈表變成紅黑樹

       第一步計算哈希碼,不僅調用了hashCode(),有進行了多次散列。目的在於key不同,哈希碼儘量不同,減少衝突

       細節:發生衝突,經過比較不存在相同key的元素,要添加一個新的節點。不是加到鏈表最後,而是添加到鏈表最前

定義Map接口

public interface Map {
    //定義方法
    void put(Object key,Object value);
    Object get(Object key);
    int size();
    boolean isEmpty();
	String toString();
	
    //定義內部接口
    interface Entry{
        public Object getKey();
        public Object getValue();
    }
}

接口的實現

public class HashMap implements Map{

    private Node[] node;
    int size;
    public HashMap(int capacity){
        node = new Node[capacity];
    }
    public HashMap(){
        this(16);   //默認初始爲16
    }

    //-------實現主要方法-------

    @Override
    public void put(Object key, Object value) {
        //計算哈希碼
        int hash = key.hashCode();
        //根據哈希碼計算存儲位置
        int index = hash % node.length;
        //如果放入數據的位置有數據
        if(node[index] != null){
            //鍵不重複
            Node current = node[index];
            while(current != null){
                //如果鍵相同
                if(current.key.equals(key)){
                    //覆蓋值
                    current.value = value;
                    //因爲鍵相同所以只是覆蓋,並非新增,因此提前return
                    //防止後面size++導致數據錯亂
                    return;
                }
                //遍歷
                current = current.next;
            }
            //創建新的節點
            Node newNode = new Node(hash,key,value);
            //讓新的節點下一個爲原來的節點
            newNode.next = node[index];
            //存儲新的開始節點
            node[index] = newNode;
        }else{
            //放入數據的位置沒有數據,直接放入
            node[index] = new Node(hash,key,value);
        }
        //如果沒有發現相同的鍵,則長度增加
        size++;
    }

    @Override
    public Object get(Object key) {
        //計算哈希碼
        int hash = key.hashCode();
        //根據哈希碼計算存儲位置
        int index = hash % node.length;
        //查找對應的Entry
        Node entry = null;
        if (node[index] != null) {
            Node currentEntry = node[index];
            while (currentEntry != null) {
                if (currentEntry.getKey().equals(key)) {
                    entry = currentEntry;
                    break;
                }
                //向後移動鏈表
                currentEntry = currentEntry.next;
            }
        }
        return entry == null ? null : entry.getValue();
    }

    @Override
    public String toString(){
        StringBuilder builder = new StringBuilder("{");
        for(int i=0;i<node.length;i++){
            if(node[i] != null){
                Node entry = node[i];
                while(entry != null){
                    builder.append(entry.getKey()+"="+entry.getValue()+",");
                    entry = entry.next;
                }
            }
        }
        if(builder.length()!=1){
            //刪除逗號
            builder.deleteCharAt(builder.length()-1);
        }
        builder.append("}");
        return builder.toString();
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    //-------定義內部類實現Entry接口-------
    class Node implements Map.Entry{
        int hash;            //存儲鍵的哈希碼
        Object key;          //鍵
        Object value;        //值
        Node next;          //下一個節點

        @Override
        public Object getKey() {
            return key;
        }

        @Override
        public Object getValue() {
            return value;
        }
        //-------構造-------
        public Node() { }
        public Node(int hash, Object key, Object value) {
            this.hash = hash;
            this.key = key;
            this.value = value;
        }
        public Node(int hash, Object key, Object value, Node next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
        //-------toString-------
        public String toString() {
            if (next != null) {
                return "{" + key + ":" + value + "-" + hash + " " + next + "}";
            } else {
                return "{" + key + ":" + value + "-" + hash + "}";
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章