仿写HashMap源码

主要是通过get和put方法来理解Hashmap来理解HashMap如何存键值对,没有涉及太深,红黑树请绕行

先贴出手写的HashMap的demo

一、定义Map接口

public interface Map<K,V> {

    /**
     * 向Map中插入值
     */
    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);
    }
}

这个Map接口中只简单的定义了map中的几个主要的函数,用来理解HashMap

二、定义HashMap实现Map接口

public class HashMap<K,V> implements Map<K,V>{

    //  集合中的元素个数
    private int size;

    private static double factory=0.75D;

    //扩容,并且重新排列元素
    private void resize(){
        //翻倍扩容
        //1、创建新的array,临时变量
        Node<K,V>[] temp=new Node[defaultLength << 1];
        //2、重新计算散列值,插入到新的array中去,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;
                node.next=temp[index];
                temp[index]=node;
                node=next;
            }
        }
        //3、替换老array
        array=temp;
        defaultLength=temp.length;
        temp=null;
    }



    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.println("下标["+i+"]");
                while(node!=null){
                    System.out.println("[+"+node.getKey()+":"+node.getValue()+"]");
                    if(node.next!=null){
                        node=node.next;
                    }else{
                        //尾部元素,跳出循环
                        node=null;
                    }
                }
                System.out.println();
            }
        }
    }
    //数据存储的结构
    Node<K,V>[] array=null;

    //数组/hash桶的长度
    private static int defaultLength=16;


    @Override
    public V put(K k, V v) {
        //1、懒加载机制,使用的时候进行分配
        if(array==null){
            array=new Node[defaultLength];
        }
        //2、通过hash算法,计算出具体插入的值的位置
        int index=position(k,defaultLength);
        //3、放入要插入的元素
        Node<K,V> node=array[index];
        if(node==null){ //如果当前位置没有元素
            array[index]=new Node<>(k,v,null);
            size++;
        }else{
            if(k.equals(node.getKey())||k==node.getKey()){
                return node.setValue(v);
            }else{
                array[index]=new Node<>(k,v,node);
                size++;
            }
        }
        return null;
    }

    private int position(K k,int length){
        int code =k.hashCode();
        //取模算法
        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{
                        //如果不同,调到下一个元素
                        node=node.next;
                    }
                }
        }
        return null;
    }

    @Override
    public int size() {
        return this.size;
    }
    static class Node<K,V> implements Map.Entry<K,V>{

        K key;
        V value;
        Node<K,V> next;


        @Override
        public K getKey() {
            return this.key;
        }

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

        public Node(K key, V value, Node<K, V> next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        /**
         * 返回原来的旧值
         */
        @Override
        public V setValue(V v) {
            V oldValue=this.value;
            this.value=v;
            return oldValue;
        }
    }
}

put方法:

HashMap采用懒加载机制,对HashMap的数组在使用的时候进行分配,map.put("admin","123456"),当向HashMap中put一个键值对时,首先通过这个字符串对象“admin”,调用hashCode方法,计算出它的hashcode值,然后通过hashcode%(数组长度-1)运算,求出你要存放k为admin的下标,然后根据下标进行存,如果该位置没有键值对,直接存下,如果有,那就要考虑你存的值是否重复,有重复则替换,无重复,则把新元素放在该位置,旧值像链表一样连在新元素的后面,最后返回旧值(put方法是有返回值的)

get方法:

同样,首先通过你传入的Key值计算出相应的数组下标值,然后遍历这个数组,查找和你key相等的:key.equals(k),来找出你要get的值

三、Test测试类:

public class Test {
    public static void main(String[] args) {
        HashMap<String,String> map=new HashMap<>();
        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.put("012号","012");
        map.put("013号","013");
        map.put("014号","014");
        map.put("015号","015");
        map.put("016号","016");
        map.put("017号","017");
        map.put("018号","018");
        map.put("019号","019");
        map.put("020号","020");
        map.put("021号","021");
        map.put("022号","022");
        map.put("023号","023");
        map.print();
        System.out.println(map.get("012"));
        System.out.println(map.get("009号"));
    }
}

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值