其他分享
首页 > 其他分享> > 手写迷你hashMap

手写迷你hashMap

作者:互联网

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