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对应的Entry
public 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;
}
// ///////////////////////////////////////////////////////////////////////////////////////////////////
// 判断是否有value
public 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;
}
// addEntry
private 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);
}
}
}
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取hashCode
private 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);
}
}
HashMap
最新推荐文章于 2024-12-09 19:59:05 发布