手写HashMap

Java 手写简单的hashmap

Posted by JYH on August 16, 2018

手写个Hashmap 方便自己理解底层数据结构

hashmap的原理我就不在这里多写了,网上很多很多 所以就直接上代码吧

先写对外的接口,get和put方法

//代码
public interface MyMap<K, V> {

    public V put (K k, V v);
    public V get (K k);
   
    interface Entry<K, V> {
        public K getKey();
        public V getValue();
    }

}

其中定义了一个内部接口

实现内部接口

 class Entry<K, V> implements MyMap.Entry<K, V> {
        
     //其实还有个hash值 但是简易的 就不写了
     private K key;
     private V value;
     private Entry<K, V> next;
 
     public Entry() {
     }
 
     public Entry(K key, V value, Entry<K, V> next) {
         this.key = key;
         this.value = value;
         this.next = next;
     }
 
     @Override
     public K getKey() {
         return key;
     }
 
     @Override
     public V getValue() {
         return value;
     }
 
 }

实现外部接口 定义一些属性

 //数组默认初始长度 使用位移运算符 1左移4位 不懂的去看二进制=。=
 private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

 //阈值比例 默认0.75
 private static final float DEFAULT_LOAD_FACTOR = 0.75f;

 private int defaultInitSize;
 private float defaultLoadFactor;

 //map中entry的数量
 private int entryUseSize;

 //数组
 private Entry<K, V>[] table = null;
 
 public MyHashMap(){
         this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
     }
 
     public MyHashMap(int defaultInitialCapacity, float defaultLoadFactor) {
 
         if (defaultInitialCapacity < 0) {
             throw new IllegalArgumentException("Illegal initial capacity: " +
             defaultInitialCapacity );
         }
 
         if (defaultLoadFactor <= 0 || Float.isNaN(defaultLoadFactor)) {
             throw new IllegalArgumentException("Illegal load factor: " +
             defaultLoadFactor);
         }
 
         this.defaultInitSize = defaultInitialCapacity;
         this.defaultLoadFactor = defaultLoadFactor;
 
         table = new Entry[this.defaultInitSize];
 
 
 
     }
 
     @Override
     public V put(K k, V v) {
         V oldValue = null;
         //是否需要扩容
         //扩容完毕 重新散列
         if (entryUseSize >= defaultInitSize * defaultLoadFactor) {
             resize(2 * defaultInitSize);
         }
         //得到hash值 计算数组中的位置
         int index = hash(k) & (defaultInitSize - 1);
         if (table[index] == null) {
             table[index] = new Entry<K, V>(k, v, null);
             ++entryUseSize;
         } else { // 遍历单链表
             Entry<K, V> entry = table[index];
             Entry<K, V> e = entry;
             while (e != null) {
                 if (k == e.getKey() || k.equals(e.getKey())) {
                     oldValue = e.value;
                     e.value = v;
                     return oldValue;
                 }
                 e = e.next;
             }
             table[index] = new Entry<K, V>(k, v, entry);
             ++entryUseSize;
 
         }
         return oldValue;
     }
 
     @Override
     public V get(K k) {
         int index = hash(k) & (defaultInitSize - 1);
 
         if (table[index] == null) {
             return null;
         } else {
             Entry<K, V> entry = table[index];
             do {
                 if (k == entry.getKey() || k.equals(entry.getKey())) {
                     return entry.getValue();
                 }
                 entry = entry.next;
             } while (entry != null);
         }
         return null;
     }
 
 
     private int hash(K k) {
         int hashcode = k.hashCode();
         hashcode ^= (hashcode >>> 20) ^ (hashcode >>> 12);
         return hashcode ^ (hashcode >>> 7 ) ^ (hashcode >>> 4);
     }
 
     private void resize(int i) {
         //改变数组大小
         Entry[] newTable = new Entry[i];
         defaultInitSize = i;
         entryUseSize = 0;
         rehash(newTable);
     }
 
     private void rehash(Entry<K, V>[] newTable) {
         //得到原来entry集合
         List<Entry<K, V>> entryList = new ArrayList<Entry<K, V>>();
         for (Entry<K, V> entry : table) {
             if (entry != null) {
                 do {
                     entryList.add(entry);
                     entry = entry.next;
                 } while (entry != null);
             }
         }
         //覆盖旧的引用
         if (newTable.length > 0 ) {
             table = newTable;
         }
         //重新put entry
         for (Entry<K, V> entry : entryList) {
             put(entry.getKey(), entry.getValue());
         }
 
 
     }
 
 
     class Entry<K, V> implements MyMap.Entry<K, V> {
 
         private K key;
         private V value;
         private Entry<K, V> next;
 
         public Entry() {
         }
 
         public Entry(K key, V value, Entry<K, V> next) {
             this.key = key;
             this.value = value;
             this.next = next;
         }
 
         @Override
         public K getKey() {
             return key;
         }
 
         @Override
         public V getValue() {
             return value;
         }
 
     }