手写一个我的HashMap

/*
 *@description: Map接口定义
 *@author: winyinghouse
 *@date:2021/3/7
 */
public interface Map<K,V> {
    V put(K k ,V v);
    V get(K k);
    void resize();

    interface Entry<K,V>{
    }
}
/*
 *@description: HashMap实现
 *@author: winyinghouse
 *@date:2021/3/7
 */
public class HashMap<K, V> implements Map<K,V> {
    Entry<K,V> table[] = null;
    int length;
    int size;
    //默认值
    final int DEFAULT_LENGTH =16;
    final double LOADFACTOR = 0.75;

    /*
    构造方法
     */
    public HashMap() {
        this.table = new Entry[DEFAULT_LENGTH];
        this.length = DEFAULT_LENGTH;
        this.size = 0;
    }

    /*
    put方法
     */
    @Override
    public V put(K k, V v) {
        int index = hash(k);
        Entry<K,V> entry = table[index];
        if(entry == null){
            table[index] = new Entry<>(k,v,k.hashCode(),null);   //若桶没有结点,则直接放进去
        }
        else{
            Entry<K,V> p = table[index];
            //这里while也是在寻找是否有相同的key值的结点,有就覆盖value值,其实可以直接调用findequalsk方法
            //只是两者实现不同,这里是循环,findequalsk是递归实现。
            while(p!=null){
                if(p.getKey() == k || p.getKey().equals(k)){
                    p.setV(v);
                    return p.getValue();
                }
                p = p.next;
            }
            //若不存在,则直接头插法
            table[index] = new Entry<>(k,v,k.hashCode(),table[index]);
        }
        size++;                                                     //数量+1
        if(size>((length * LOADFACTOR)) && table[index] != null ) {   //1.7扩容条件,数量超过阈值,并且存在哈希冲突
            resize();           //扩容
            index = hash(k);    //再算一下扩容后的结点所在的索引
        }
        return table[index].getValue();    //返回插入结点的value
    }

    /*
    get函数
     */
    @Override
    public V get(K k) {
        if(size == 0){
            return null;
        }
        int index = hash(k);
        if(table[index] != null) {
            return findequalsk(table[index],k);    //寻找
        }
        return null;
    }

    /*
    扩容函数
     */
    @Override
    public void resize() {
        size = 0;
        Entry<K,V> p;
        int oldLength = length;
        Entry<K,V>[] oldTable = table;
       length = oldLength * 2;              //数组长度扩大到原来2倍
        table = new Entry[length];          //初始化扩容的数组
        int i = 0;
        //遍历旧数组
        while(i<oldTable.length){
             p = oldTable[i];
             //遍历旧数组上的桶
            while(p !=null){
                int newIndex = p.getHash()%length;
                Entry<K,V> temp = p;
                p = p.next;                             //头插法会破坏连接关系,保留插入前的下一个结点
                put(temp.getKey(), temp.getValue());   //将元素一个一个放入新数组
            }
            i++;
        }
    }

    //递归找到相同key的结点
    private V findequalsk(Entry<K,V> p, K k) {
        if(p.getKey() == k || p.getKey().equals(k)){
            return p.getValue();
        }
        if(p.next != null){
            return findequalsk(p.next,k);
        }
        return null;
    }
    //直接就是求索引的函数,没有扰动处理
    private int hash(K k){
        int index = k.hashCode()%length;
        return index > 0? index:-index;   //hashcode可能为负数
    }



/*
1.7hashmap内部类Entry
 */
    class Entry<K,V> implements Map.Entry<K,V>{
        K k;
        V v;
        int hash;
        Entry<K,V> next;
        public void setK(K k) {
            this.k = k;
        }
        public void setV(V v) {
            this.v = v;
        }
        public int getHash() {
            return hash;
        }
        public void setHash(int hash) {
            this.hash = hash;
        }
        public Entry(K k, V v, int hash, Entry<K,V> next) {
            this.k = k;
            this.v = v;
            this.hash = hash;
            this.next = next;
        }
        public K getKey() {
            return k;
        }
        public V getValue() {
            return v;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值