ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

手写迷你hashMap

2021-09-08 16:01:52  阅读:171  来源: 互联网

标签:map hashMap 迷你 index next Entry entry 手写 null


public interface MyMap<K,V> {

V put(K k,V v);

V get(K k);

interface Entry<K,V>{
    K getKey();

    V getValue();
}

}

public class MyHashMap<K,V> implements MyMap<K,V> {

//默认容量
private static int defaultLength = 16;
//加载因子
private static float defaultLoad = 0.75f;
//Map使用数组长度
private int size = 0;
//声明数组
private Entry<K,V>[] map = null;


public MyHashMap(){
    map = new Entry[defaultLength];
}


    /**
 * 储存结构
 * @param <K>
 * @param <V>
 */
@Setter
@Getter
class Entry<K,V> implements MyMap.Entry<K,V>{
    private K key;
    private V value;
    //下标
    int index;
    //链表指向下一个
    private Entry<K,V> next;

    public Entry(K k,V v,Entry<K,V> entry,int inx){
        this.key = k;
        this.value = v;
        this.index = inx;
        this.next = entry;
    }
}
  1. put方法被调用时,HashMap会根据key计算出对应的hashcode,然后根据hashcode确定该Entity应该存放在数组的哪个位置

  2. HashMap发生hash碰撞如果发现hashcode已经存在,则会对key进行euqals对比

  3. equals结果是true,则认为确实是同一个key,然后将新的value覆盖旧的value(此时put方法将会返回旧value值)。

  4. equals结果是false,则认为是hash碰撞,此时会将之前的Entity作为新Entity的next,此时形成一个链表,新Entity则处在链表的首位。

      public V put(K k, V v) {
     int index = getIndex(k,map.length);
     Entry<K,V> entry = map[index];
     if(entry == null){
         map[index] = new Entry(k,v,null,index);
     } else {
         while (entry.next != null) {
             if (k.equals(entry.getKey())) {
                 entry.value = v;
             }
         }
         map[index] = new Entry(k, v, entry, index);
     }
     size++;
     if(size > defaultLength*defaultLoad){
         resize();
     }
     System.out.println("添加 key:"+k+"成功下标"+index);
     return v;
    

    }

    /**

    • 获取下标
    • @param k 键值
    • @return length 下标
      */
      private int getIndex(K k,int length){
      int m = length -1 ;
      return k.hashCode() & m;
      }

根据key计算hashcode,然后得出其数组下标,去对应位置获取链表。
从头到尾遍历链表的每一个Entity,通过equals方法找到对应的Entity。

public V get(K k) {
    int index = getIndex(k,map.length);
    Entry<K, V> entry = map[index];
    while (entry != null && entry.next != null) {
        if (entry.getKey() == k || (entry.getKey() != null && entry.getKey().equals(k))) {
            return entry.getValue();
        } else {
            entry = entry.next;
        }
    }
    if (entry.next == null) {
        if (entry.getKey() == k || (entry.getKey() != null && entry.getKey().equals(k))) {
            return entry.getValue();
        }
    }
    return null;
}

阈值=容量*加载因子。默认12。当元素数量超过阈值时便会触发扩容,每次增长都是2倍

   private void resize() {
    Entry<K,V>[] newMap = new Entry[2*defaultLength];
    System.out.println("开始进行扩容,扩容前大小:"+ map.length);
    Entry[] oldMap = map;
    for (int j = 0; j < oldMap.length; j++) {
        Entry<K,V> e = oldMap[j];
        if (e != null) {
            oldMap[j] = null;
            do {
                Entry<K,V> next = e.next;
                //当数组扩容后需要数组数量按新map重新计算每个元素的下标,否则读取时计算下表出错
                int i = getIndex(e.key,newMap.length);
                e.next = newMap[i];
                newMap[i] = e;
                e = next;
            } while (e != null);
        }
    }
    map = newMap;
    //扩容成功 更新数组长度
    defaultLength = 2*defaultLength;
    System.out.println("开始进行扩容,扩容后大小:"+ map.length);
}

下篇文章更新链表转换红黑树

标签:map,hashMap,迷你,index,next,Entry,entry,手写,null
来源: https://blog.csdn.net/weixin_43861113/article/details/118366795

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有