//hashmap实现了Map接口,并继承了AbstractMap类
//map接口里面定义了键值对。
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
}
//其有四个构造方法:
//第一个是创造了一个一定容量和阈值的空的hashmap
public HashMap(int initialCapacity, float loadFactor) {
//传入空间为空,抛出异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
//传入空间如果太大,则规定为最大空间。
//static final int MAXIMUM_CAPACITY = 1 << 30;
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
//负载因子小于0,则抛出异常
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
//将传进来的负载因子赋值给创建的hashmap
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
//确定hashmap的空间,需要保证其为2的幂
static final int tableSizeFor(int cap) {
//-1在二级制中是32个1表示的,
int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
//这个是返回数字最高位0的个数
//二分的思想:先确定其在哪一位(16位左边高位?还是右边低位),继续二分,直到确定其位置
//然后可以得出其高位至少有的0的个数,再将其划分区间的右边低位全部通过“>>>”方式去掉。n代表其最大可能的0的个数,n也同时更新。
public static int numberOfLeadingZeros(int i) {
// HD, Count leading 0's
if (i <= 0)
return i == 0 ? 32 : 0; //传进来的为0的话,返回32个0
int n = 31;
if (i >= 1 << 16) { n -= 16; i >>>= 16; }
if (i >= 1 << 8) { n -= 8; i >>>= 8; }
if (i >= 1 << 4) { n -= 4; i >>>= 4; }
if (i >= 1 << 2) { n -= 2; i >>>= 2; }
return n - (i >>> 1);
}
//第二个是创建一定空间的空hashmap
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
//第三个是无参构造
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
//第四个是创建一个与指定Map有相同映射的hashmap
//??????????
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
这里面节点的定义如下:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
可以看出来,其实现了map.entry接口,这是键值对实现的节点,存储的是键值对。
(本来打算把源码好好看一下,写好了再发上来,可是时间不够,而且那个树节点的增减看着头痛,以后有机会再看吧)