手写hashMap

本文介绍了一个简单的自定义HashMap实现,包括其基本结构、存储与检索机制、扩容策略等关键部分。通过对核心代码的解析,帮助读者理解HashMap的工作原理。

/***

  • 手写hashmap

  • @param

  • @param
    */
    public class MbHMap<K, V> implements MbMap<K, V> {

    public static int defultLength = 16;

    //定义一个HashMap骨架数组
    public Entry<K, V>[] table = null;

    //扩容标准 数组总长度/以使用数组长度
    private static double defultAddSizeFactor = 0.75;
    //以使用的数组
    private int userSize;

    public MbHMap() {
    this(defultLength, defultAddSizeFactor);
    }

    //数组长度 ,扩容标准
    public MbHMap(int length, double defultAddSizeFactor) {
    if (length < 0) {
    throw new IllegalArgumentException(“数组参数不能为负数”);
    }

     if (defultAddSizeFactor <= 0 || Double.isNaN(defultAddSizeFactor)) {
         throw new IllegalArgumentException("扩容标注必须大于0");
     }
    
     this.defultLength = length;
     this.defultAddSizeFactor = defultAddSizeFactor;
     table = new Entry[length];
    

    }

    /***

    • 快速存储

    • @param k

    • @param v

    • @return
      */
      public V put(K k, V v) {
      if (userSize > defultAddSizeFactor * defultLength) {
      //扩容
      up2Size();
      }
      //通过key来找到存储位置
      int index = getIndex(k, table.length);
      //拿到对应entry值
      Entry<K, V> entry = table[index];

      if (entry == null) {
      table[index] = new Entry(k, v, null);
      userSize++;
      } else { //Entry有值时
      table[index] = new Entry(k, v, entry);
      }
      return entry.getValue();
      }

    //扩容2倍
    private void up2Size() {
    // 16 * 2
    Entry<K, V>[] newTable = new Entry[2 * defultLength];

     //将散列的数组再次散列
     againHash(newTable);
    

    }

    private void againHash(Entry<K, V>[] newTable) {
    //将数组对象封装List
    List<Entry<K, V>> entrylist = new ArrayList<Entry<K, V>>();

     for (int i = 0; i < table.length; i++) {
         if (table[i] == null) {
             continue;
         }
    
         fundEntryByNext(table[i], entrylist);
     }
    
     if (entrylist.size() > 0) {
         userSize = 0;
         defultLength = 2 * defultLength;
         table = newTable;
         //将最上面一个entry对象 next情况
         for (Entry<K, V> entry : entrylist) {
             if (entry.next != null) {
                 entry.next = null;
             }
    
             put(entry.getKey(), entry.getValue());
         }
     }
    

    }

    //根据entry 选择下一个entry
    private void fundEntryByNext(Entry<K, V> entry, List<Entry<K, V>> entrylist) {
    if (entry != null && entry.next != null) {
    entrylist.add(entry);
    //递归加集合中
    fundEntryByNext(entry.next, entrylist);
    } else {
    entrylist.add(entry);
    }

    }

    //通过数组长度 ,和k的位置 来找到Entry 存放位置
    public int getIndex(K k, int length) {

     int m = length - 1;
     int index = hash(k.hashCode()) & m;
     //三木运算符保证数据正确
     return index >= 0 ? index : -index;
    

    }

    //找到自己的Hash算法
    private int hash(int hashCode) {
    hashCode = hashCode ^ ((hashCode >>> 20)) ^ (hashCode >>> 12);

     return hashCode ^ ((hashCode >>> 7)) ^ (hashCode >>> 4);
    

    }

    /***

    • 快取

    • @param k

    • @return
      */
      @Override
      public V get(K k) {

      int index = getIndex(k, table.length);
      if (table[index] == null) {
      throw new NullPointerException(“空指针异常”);
      }

      return findValueByEqualKey(k, table[index]);
      }

    /**

    • 通过key找到实体对象

    • @param k

    • @param entry

    • @return
      */
      private V findValueByEqualKey(K k, Entry<K, V> entry) {

      if (k == entry.getKey() || k.equals(entry.getKey())) {
      return entry.getValue();
      } else if (entry.next != null) {
      return findValueByEqualKey(k, entry.next);
      }

      return null;
      }

    /**

    • 内部类

    • @param

    • @param
      */
      class Entry<K, V> implements MbMap.Entry<K, V> {

      K k;
      V v;
      Entry<K, V> next; //指向被this积压的entry对象

      public Entry(K k, V v, Entry<K, V> next) {
      this.k = k;
      this.v = v;
      this.next = next;
      }

      @Override
      public K getKey() {
      return k;
      }

      @Override
      public V getValue() {
      return v;
      }

    }

    public int userSize() {
    return userSize;
    }

    public static int getDefultLength() {
    return defultLength;
    }

    public static void setDefultLength(int defultLength) {
    MbHMap.defultLength = defultLength;
    }

    public Entry<K, V>[] getTable() {
    return table;
    }

    public void setTable(Entry<K, V>[] table) {
    this.table = table;
    }

    public static double getDefultAddSizeFactor() {
    return defultAddSizeFactor;
    }

    public static void setDefultAddSizeFactor(double defultAddSizeFactor) {
    MbHMap.defultAddSizeFactor = defultAddSizeFactor;
    }

    public int getUserSize() {
    return userSize;
    }

    public void setUserSize(int userSize) {
    this.userSize = userSize;
    }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值