hashtable
- 线程安全
- 键/值不可为null
- 无序
- 已被淘汰掉
实现
public class test_01 {
public static void main(String[] args) throws IOException {
/*
初始化数组大小为11,数组加载因子0.75f
public Hashtable() {
this(11, 0.75f);
}
*/ Hashtable map = new Hashtable();
//添加key-value
map.put(1,1);
map.put("",1);
map.put(1,"");
map.put(2,2);
System.out.println(map);
}
}
- map.put(k,v);
public synchronized V put(K key, V value) {
// value为null 抛出异常
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
//获取hash值
int hash = key.hashCode();
//根据hash值计算index下标
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
//获取当前entry对象
Entry<K,V> entry = (Entry<K,V>)tab[index];
//循环当前链表
for(; entry != null ; entry = entry.next) {
//判断hash值和key是否已经存在,如果存在,替换value
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//如果下标中不存在节点,添加一个新的节点
addEntry(hash, key, value, index);
return null;
}
- addEntry(hash, key, value, index);
private void addEntry(int hash, K key, V value, int index) {
//操作数+1
modCount++;
Entry<?,?> tab[] = table;
//如果存储的数据达到阀值
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
//刷新表
rehash();
tab = table;
//计算hash值
hash = key.hashCode();
//获取下标
index = (hash & 0x7FFFFFFF) % tab.length;
}
// 创建新的entry对象
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
//添加节点
tab[index] = new Entry<>(hash, key, value, e);
//数据量+1
count++;
}
- rehash();
protected void rehash() {
//获取当前数组长度
int oldCapacity = table.length;
//获取当前数组
Entry<?,?>[] oldMap = table;
// 扩容 -> 大小为 (length * 2 + 1)
int newCapacity = (oldCapacity << 1) + 1;
//判断扩容后的大小是否超出最大数组长度
if (newCapacity - MAX_ARRAY_SIZE > 0) {
//如果扩容前的数组长度 = 最大数组长度 , 结束
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
//否则最大数组长度就为扩容后的长度
newCapacity = MAX_ARRAY_SIZE;
}
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
//操作数 + 1
modCount++;
//扩容临界点 = min[(扩容后的长度 * 0.75),(最大数组长度 + 1)]
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
//数组 = 扩容后的数组
table = newMap;
//将原数组的数据 赋予新的数组
for (int i = oldCapacity ; i-- > 0 ;) {
//循环原数组
for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
//获取原数组的节点
Entry<K,V> e = old;
//old节点 = old节点的下一个节点
old = old.next;null
//按扩容后的数组大小重新计算当前节点的下标
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
//原数组当前节点下一个节点 = 新的下标节点
e.next = (Entry<K,V>)newMap[index];
//计算的新的下标的节点 = 原数组下标节点
newMap[index] = e;
}
}
}
END