HashMap 的简介
- Hashmap是一个散列桶(bucket ),存储的一对一对的数据,形式是:key---value。
- Hashmap采用的是数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改。
- HashMap 线程不安全,所以 HashMap 很快。
- HashMap 可以接受 null 键和值,而 Hashtable 则不能。
HashMap 的工作原理
在使用put(key,value)方法向map中插入值得时候,会优先调用hash()方法,参数为key,意思就是先获取key得hashcode,计算需要将该key放入的位置。这里关键点在于指出,HashMap 是在 bucket 中储存键对象和值对象,作为Map.Node 。下面可以了解一下Hashmap的实现:
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;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
解释:Node是Hashmap类的一个静态内部类,实现了Map.Entry<K,V>接口。里面存放的key,value,hash这几个参数共同组成了hashmap的数组需要的参数,而next是组成链表的重要成员。他们共同组成了NODE这个对象,NODE对象共同组成了Hashmap 的主要结构。
注意:
● HashMap数组:transient Entry[] table
● 数组默认长度:static final int DEFAULT_INITIAL_CAPACITY = 1 << 4=16
● 数组最大长度:static final int MAXIMUM_CAPACITY = 1 << 30=1073741824
● 默认加载因子:static final float DEFAULT_LOAD_FACTOR = 0.75f
● 扩容临界值:private int threshold;(threshold=capcity*loadFactor)
DEFAULT_INITIAL_CAPACITY 是数组默认的长度即16,MAXIMUM_CAPACITY 是数组最大的长度2的30次方,原因是2的31次方就超过Integer.MAX_VALUE(2147483647)了(也就是2^31-1),而数组的长度都必须是2的次方(原因稍后会解释),所以数组最大长度只能是2的30次方。
数组的长度为2的次方原因:比如我们向HashMap中存入了两个键值对entry1(key1=”abc”,value1=”ABC”)、entry2(key2=”def”,value1=”DEF”),假设key1对应的hash值为18,二进制为10010,假设key2对应的hash值为27,二进制为11011。