HashMap

来源:互联网 发布:php 获取当前端口号 编辑:程序博客网 时间:2024/05/20 09:26
package com.zhuyu_deng.test;import java.io.Serializable;/** 属性: Entry[] table; 数组结构,Entry,结点,可延伸做链表(Entry)内部重新equals(),hashCode(),toString(); * currentSize,当前大小 * modCount,修改次数,HashMap是非同步的,当迭代器运行的时候,有其他的线程修改HashMap的时候,会fast-fail * threshold,阈值,权衡空间与查找时间,由table的长度length和加载因素LOADFACOR决定的。 * LOAD_FACTOR,加载因素 * 表的默认大小,为2的幂(必须),DEFAULT_TABLE_SIZE; *  * 对外接口:对外接口往往够过调用内部接口完成功能 * 构造函数:1.HashMap()     经验:在初始化属性时,最好将多个构造函数最终调用到一个构造函数中,由一个构造函数完成属性初始化。 *   2.HashMap(tableSize) 加载因素一律使用默认的LOAD_FACTOR = 0.75F; *   3.V put(K key, V value); *   4.V get(Object key);  // 除了put,其他的关于Key的参数都是Object,会调用到查找,无论是内部还是外部,被调用的函数参数为Object key *  5. void clear(); *  6. int size(); *  7. boolean isEmpty(); *  8. containsKey(); * 内部接口: */public class MyMap<K, V> implements Serializable{//属性private static int DEFAULT_TABLE_SIZE = 16;private int currentSize;private Entry[] table;private int modCount;private int threshold;private static float LOAD_FACTOR = 0.75F;private static class Entry<K, V>{final int hash;Entry<K, V> next;K key;V value;public Entry(int h, Entry<K, V> e, K k, V v){hash = h;next = e;key = k;value = v;}public K getKey(){return key;}public V getValue(){return value;}public V setValue(V newValue){V oldValue = value;value = newValue;return oldValue;}public boolean equals(Object o){if (!(o instanceof Entry))return false;Entry e = (Entry) o;Object k1 = getKey();Object k2 = e.getKey();//== or equals(),相等if (k1 == k2 || (k1 != null && k1.equals(k2))){Object v1 = getValue();Object v2 = e.getValue();if (v1 == v2 || (v1 != null && v1.equals(v2)))return true;}return false;}public int hashCode(){return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());}public String toString(){return getKey() + " = " + getValue();}}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////构造函数//有多个构造函数,但是让这些构造函数都调用一个构造函数public MyMap(){this(DEFAULT_TABLE_SIZE);}public MyMap(int n){int capacity = 1;while (capacity < n)capacity <<= 1;table = new Entry[capacity];threshold = (int) (capacity * LOAD_FACTOR);}/////////////////////////////////////////////////////////////////////////////////////清空public void clear(){modCount++;Entry[] tab = table;for (int i = 0; i < tab.length; ++i)tab[i] = null;currentSize = 0;}//返回元素个数public int size(){return currentSize;}//返回容量public int capacity(){return table.length;}//判空public boolean isEmpty(){return currentSize == 0;}///////////////////////////////////////////////////////////////////////////////////////////////////判断是否有key对应的Entrypublic boolean containsKey(Object key){return getEntry(key) != null;}//返回key对应的Entry<K, V>对应private Entry<K, V> getEntry(Object key){int hashCode = hash(key.hashCode());for (Entry<K, V> e = table[indexFor(hashCode, table.length)]; e != null; e = e.next){Object k;if (hashCode == e.hash && ((k = e.key) == key || (k != null && k.equals(key))))return e;}return null;}///////////////////////////////////////////////////////////////////////////////////////////////////////判断是否有valuepublic boolean containsValue(Object value){if (value == null)return containsNullKey();Entry[] tab = table;for (int i = 0; i < tab.length; ++i){for (Entry<K, V> e = table[i]; e != null; e = e.next){Object k = e.value;if (value.equals(k))return true;}}return false;}private boolean containsNullKey(){Entry[] tab = table;for (int i = 0; i < tab.length; ++i){for (Entry<K, V> e = table[i]; e != null; e = e.next){if (e.value == null)return true;}}return false;}//取出public V get(Object key){if (key == null)return getForNullKey();int hashCode = hash(key.hashCode());for (Entry<K, V> e = table[indexFor(hashCode, table.length)]; e != null; e = e.next){Object k;if (e.hash == hashCode && ((k = e.key) == key || k.equals(key))){return e.value;}}return null;}private V getForNullKey(){for (Entry<K, V> e = table[0]; e != null; e = e.next){if (e.key == null)return e.value;}return null;}//添加public V put(K key, V value){if (key == null)return putForNullKey(value);int hashCode = hash(key.hashCode());int i = indexFor(hashCode, table.length);for (Entry<K, V> e = table[i]; e != null; e = e.next){Object k;if (hashCode == e.hash && ((k = e.key) == key || e.equals(key))){V oldValue = e.value;e.value = value;return oldValue;}}modCount++;addEntry(hashCode, i, key, value);return null;}//private V putForNullKey(V value){for (Entry<K, V> e = table[0]; e != null; e = e.next){if (e.key == null){V oldValue = e.value;e.value = value;return oldValue;}}modCount++;addEntry(0, 0, null, value);return null;}public V remove(Object key){Entry<K, V> e = removeEntryForKey(key);return (e == null ? null : e.value);}private Entry<K, V> removeEntryForKey(Object key){int hashCode = hash(key.hashCode());for (Entry<K, V> e = table[indexFor(hashCode, table.length)]; e != null; e = e.next){Object k;if (hashCode == e.hash && (    (k = e.key) == key || (k != null && k.equals(key))   )){modCount++;currentSize--;Entry<K, V> currentEntry = e;e = e.next;return currentEntry;}}return null;}//addEntryprivate void addEntry(int hashCode, int index, K key, V value){Entry<K, V> e = table[index];  // 表table[index]被e接过来table[index] = new Entry<K, V>(hashCode, e, key, value);  // table[index]接个newEntry,然后在接e;if(currentSize++ > threshold)resize(table.length * 2);}private void resize(int newCapacity){Entry[] newTable = new Entry[newCapacity];transfer(newTable);table = newTable;threshold = (int)(LOAD_FACTOR * newCapacity);}private void transfer(Entry[] newTable){Entry[] src = table;int oldCapacity = src.length;for (int i = 0; i < src.length; ++i){Entry<K, V> e = src[i];  // e把第i个链接过来if (e != null){src[i] = null;do{Entry<K, V> next = e.next;int index = indexFor(e.hash, newTable.length);e.next = newTable[index];newTable[index] = e;e = next;}while(e != null);}}}///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 获取hashCodeprivate int hash(int h){h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);}//确定在table中的位置private int indexFor(int h, int length){return h & (length - 1);}}


原创粉丝点击