自己实现HashMap-通俗易懂

前言

HashMap的底层实现主要是基于数组和链表来实现的,HashMap中通过key的hashCode来计算hash值的,由这个hash值计算在数组中的位置,将新插入的元素放到数组的这个位置,如果新插入的元素的hash值跟这个位置上已有元素的hash值相同,就会出现hash冲突,这时候,就在该位置通过链表来插入新的元素。
参考图:http://www.cnblogs.com/chengxiao/p/6059914.html
这里写图片描述


代码实现

  1. MyMap接口
  2. MyHashMap实现类
  3. MyHashMapTest测试类

1)MyMap接口

package com.cxx.map.HashMap;
/**
 * @Author: cxx
 * 自己实现 map接口
 * @Date: 2018/6/8 11:18
 */
public interface MyMap<K,V> {
    //大小
    int size();
    //是否为空
    boolean isEmpty();
    //根据key获取元素
    Object get(Object key);
    //添加元素
    Object put(Object key,Object value);
    interface Entry<k,v>{
        k getkey();
        v getValue();
    }
}

2)MyHashMap实现类

package com.cxx.map.HashMap;
import java.util.Map;
import java.util.Set;
/**
 * @Author: cxx
 * 自己实现HashMap
 * 底层结构:数组+链表
 * @Date: 2018/6/8 11:30
 */
public class MyHashMap<K,V> implements MyMap {
    //默认容量16
    private final int DEFALUT_CAPACITY=16;
    //内部存储结构
    Node[] table = new Node[DEFALUT_CAPACITY];
    //长度
    private int size=0;
    //keySet
    Set<K> keySet;
    @Override
    public int size() {
        return this.size;
    }

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

    @Override
    public Object get(Object key) {
        int hashValue = hash(key);
        int i=indexFor(hashValue,table.length);
        for (Node node=table[i];node!=null;node=node.next){
            if (node.key.equals(key)&&hashValue==node.hash){
                return node.value;
            }
        }
        return null;
    }

    @Override
    public Object put(Object key, Object value) {
        //通过key,求hash值
        int hashValue=hash(key);
        //通过hash,找到这个key应该放的位置
        int i=indexFor(hashValue,table.length);
        //i位置已经有数据了,往链表添加元素
        for (Node node=table[i];node!=null;node=node.next){
            Object k;
            //且数组中有这个key,覆盖其value
            if (node.hash==hashValue&&((k=node.key)==key||key.equals(k))){
                Object oldValue=node.value;
                node.value=value;
                //返回oldValue
                return oldValue;
            }
        }
        //如果i位置没有数据,或i位置有数据,但key是新的key,新增节点
        addEntry(key,value,hashValue,i);
        return null;
    }

    public void addEntry(Object key,Object value,int hashValue,int i){
        //如果超过了原数组大小,则扩大数组
        if (++size==table.length){
            Node[] newTable=new Node[table.length*2];
            System.arraycopy(table,0,newTable,0,table.length);
            table=newTable;
        }
        //的到i位置的数据
        Node eNode=table[i];
        //新增节点,将该节点的next指向前一个节点
        table[i]=new Node(hashValue,key,value,eNode);
    }

    //获取插入的位置
    public int indexFor(int hashValue,int length){
        return hashValue%length;
    }
    //获取hash值
    public int hash(Object key){
        return key.hashCode();
    }

    //静态内部类:Node节点实现Entry接口
    static class Node implements MyMap.Entry{
        int hash;//hash值
        Object key;//key
        Object value;//value
        Node next;//指向下个节点(单例表)
        Node(int hash,Object key,Object value,Node next){
            this.hash=hash;
            this.key=key;
            this.value=value;
            this.next=next;
        }
        @Override
        public Object getkey() {
            return this.key;
        }

        @Override
        public Object getValue() {
            return this.value;
        }
    }
}

3)MyHashMapTest测试类

package com.cxx.map.HashMap;
import java.util.HashMap;
import java.util.Map;
/**
 * @Author: cxx
 * @Date: 2018/6/8 11:41
 */
public class TestMap {
    public static void main(String[] args) {
        MyMap map = new MyHashMap();
        map.put("a1",1);
        map.put("a2",2);
        System.out.println("size:"+map.size());
        System.out.println("isEmpty:"+map.isEmpty());
        System.out.println(map.get("a1"));
    }
}

这里写图片描述


总结

简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

猜你喜欢

转载自blog.csdn.net/m0_37499059/article/details/80623438