仿写HashMap

最近阅读了HashMap的源码,为了加深对HashMap的理解自己动手仿写了一个HashMap,

主要实现了get(),put(),resize()方法。具体的说明在代码的注释里。

public class MyHashMap<K,V> {
    private Node<K,V>[] table;
    private int size=0;
    private int capacity;
    private float loadFactor;

    /**
    * @Description: 无参构造
    * @Param: []
    * @return: []
    * @Author: Kwg
    * @Date: 2022/4/11
    */
    public MyHashMap() {
        this.capacity = 16;
        this.loadFactor = 0.75f;
        /**
         *  table = new Node<K,V>[capacity];
         *  直接这样会报错,Java是不支持实例化泛型数组的,
         *  因为Java认为数组是不可变的,而泛型数组中的元素类型是会变化的,
         *  一个解决方法,利用反射就可以实例化一个固定大小的泛型数组了
         */
        table = (Node<K, V>[]) Array.newInstance(Node.class,capacity);
    }

    /**
    * @Description: 自定义容量,负载因子的构造器
    * @Param:
    * @return:
    * @Author: Kwg
    * @Date: 2022/4/11
    */

    public MyHashMap(int initialCapacity,float loadFactor){
        //自定义容量不能小于0
        if(initialCapacity<0){
            throw new IllegalArgumentException("不合法容量:"+capacity);

        }
        //自定义负载因子不能小于等于0并且不能是NaN值
        if(loadFactor<=0||Float.isNaN(loadFactor))
            throw new IllegalArgumentException("不合法负载因子"+loadFactor);

        //容量自定义向上取2的n次方
        this.capacity=tableSizeFor(initialCapacity);
        this.loadFactor=loadFactor;
        table = (Node<K, V>[]) Array.newInstance(Node.class,capacity);

    }

    //容量自定义向上取2的n次方
    static final int tableSizeFor(int cap){
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : n + 1;

    }

    /**
     * 计算hash值
     */
    int Hash(K key){
        return Objects.hashCode(key)^(Objects.hashCode(key)>>>16);
    }

    /**
     * 计算对应的下标
     * @param hash
     * @return
     */
    int Index(int hash){
        int len=this.table.length;
        return (len-1)&hash;
    }

    /**
     * 核心方法put方法
     * @param key
     * @param value
     */
    void put(K key,V value){
        int hash=Hash(key);
        int index=Index(hash);
        //判断是发送覆盖的标记,有false,无true
        boolean flag=true;
        Node<K,V> node=new Node<>(key,value,hash);

        if(this.table[index]==null){
            table[index]=node;
        }else {
            Node<K,V> head=this.table[index];
            //搜素链表
            while (head!=null){
                //key相等则覆盖
                if(key== head.key){
                    head.value=value;
                    flag=false;
                    break;
                }
                //尾插法
                if(head.next==null){
                    head.next=node;
                    break;
                }
                head=head.next;
            }
        }
        if(flag) this.size++;
        if(size>capacity*loadFactor) resize();
    }

    /**
     * 核心方法 get
     * @param key
     * @return
     */
    V get(K key){
        V value=null;
        int hash=Hash(key);
        int index=Index(hash);
        if(this.table[index]==null){
            return value;
        }else {
            Node<K,V> head=this.table[index];
            //遍历所有节点
            while (head!=null){
                if(head.key==key){
                    value= head.value;
                    break;
                }
                head=head.next;
            }
            return value;
        }

    }

    /**
     * 扩容
     */
    void resize(){
        //老的table
        Node<K,V>[] oldTable=this.table;
        //长度*2
        this.table=(Node<K, V>[]) Array.newInstance(Node.class,2*capacity);
        this.capacity*=2;
        for(int i=0;i<oldTable.length;i++){
            if(oldTable[i]!=null){
                Node<K,V> head=oldTable[i];
                while (head!=null){
                    put(head.key, head.value);
                    head=head.next;
                }
            }
        }
    }

    public int getSize(){
        return size;
    }



    class Node<K,V>{
        K key;
        V value;
        int hash;
        Node<K,V> next;

        public Node(K key,V value,int hash){
            this.hash=hash;
            this.key=key;
            this.value=value;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值