HashMap是基于哈希表的Map接口的实现。HashMap中允许使用NULL键合NULL值。因为在扩容时会发生重构,在重构之后,索引会发生变化,说以不能保证映射的顺序,特别是它不能保证映射顺序的恒久不变。
HashMap实际上是一个数组加链表的结构,在加入一个元素之后,程序会调用 hashCode() 计算索引,然后将元素存到在数组的对应位置上,如果这个位置上已经有元素存在,那么在同一个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。
HashMap有两个影响性能的因子:初始容量和加载因子。初始容量是哈希表中位置的初始数量。加载因子是表在当前容量下,对于表可以装多满的一种衡量尺度,当表格中的数据量超出了当前容量与加载因子时,哈希表会调用rehash进行扩容(即重建内部数据结构),从而使哈希表具有大约两倍之前的桶数。因为在扩容中会队所有映射重新调用hashCode()计算索引,所以这个过程十分影响效率。因此,在建立哈希表的时候,就对容量和加载因子进行正确预估,对于提高效率十分重要。
一、HashMap的构造方法
HashMap有4种构造方法:
// 默认构造函数。
HashMap()
// 指定“容量大小”的构造函数
HashMap(int capacity)
// 指定“容量大小”和“加载因子”的构造函数
HashMap(int capacity, float loadFactor)
// 包含“子Map”的构造函数
HashMap(Map<? extends K, ? extends V> map)
其中,默认的容量大小为16,默认的加载因子为0.75。
调用的方法为:HashMap<K, V> 表名称 = new HashMap<K, V>()。
public class HashMapDemo {
public static void main(String[]args) {
HashMap<String, String> hm = new HashMap<String, String>();
}
}
二、HashMap的存取元素
1. put(K key, V value)
put方法是我们用来向HashMap中添加元素的方法,key是指定值将要关联的键,value是指定键将要关联的值。
public V put(K key, V value) {
// 若“key为null”,调用putForNullKey方法,将value放置在数组第一个位置
if (key == null)
return putForNullKey(value);
// 若“key不为null”,则根据key的keyCode重新计算hash值
int hash = hash(key.hashCode());
// 搜索指定hash值在对应table中的索引
int i = indexFor(hash, table.length);
// 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
// 若key对应的键值对已经存在,则用新的value取代旧的value,并将旧的value返回!
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
// 若“该key”对应的键值对不存在,则将“key-value”添加到索引i处
modCount++;
addEntry(hash, key, value, i);
return null;
}
HashMap实际上是一个数组加链表的结构,在加入一个元素之后,程序会调用 hashCode() 计算索引,然后将元素存到在数组的对应位置上,如果这个位置上已经有元素存在,那么在同一个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。
2. public V get(Object key)
public V get(Object key) {
//如果key为空,则getForNullKey,返回数组第一个位置的值
if (key == null)
return getForNullKey();
//如果key不为空,则根据key的值计算hashcode
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}