直接上代码;
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(); } }
public class MyHashMap<K,V> implements MyMap<K,V> { //数组的默认初始长度 private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //阈值 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); } //计算数组中的位置 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;//更新value return oldValue; } e = e.next; } table[index] = new Entry<K,V>(k,v,entry);//形成新的Entry,挤压单链表(entry成为next) ++entryUseSize; } 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; } //所谓重新hash,就是重新put entry到hashmap for(Entry<K,V> entry : entryList){ put(entry.getKey(),entry.getValue()); } /** * 这里可以看出,hashMap频繁进行resize/reshash操作是会影响性能的。 * resize/rehash的过程,就是数组变大,原来的数组中的entry元素一个个的put到新的数组的过程,需要注意的就是一些状态量的变更。 */ } @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())){//== or equals来判断取值 return entry.value; } entry = entry.next; }while (entry != null); } return null; } /** * HashMap单链表 * @param <K> * @param <V> */ 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; } } }
测试一下;
public static void main(String[] args) { MyHashMap<String,String> myMap = new MyHashMap<>(); for (int i = 0; i < 20 ; i++){ myMap.put("key"+i,"value"+i); } for (int i = 0; i < 20 ; i++){ System.out.println(myMap.get("key"+i)); } }