java数据结构之HashMap
万事开头难,懒惰一段时间后,想写些东西,发现不知道从何下笔,那就先从HashMap开始。
这是很早之前梳理java数据结构画得一张图,从这里我们可以看到,java collection主要包括Map和Collection两个接口,这里先说下Map这个接口。
An object that maps keys to values. A map cannot contain duplicate keys;each key can map to at most one value.
这是Map接口的简介,简单说Map就是一中key-value的数据结构,Map不能包含重复的key,每个key只能对应一个value。
看下Map接口的方法,一目了然,基本根据方法名称就可以看出这个方法表示什么。
Map的下一层就是AbstractMap,关于AbstractMap这个类的介绍如下
This class provides a skeletal implementation of the Map interface, to minimize the effort required to implement this interface.
AbstractMap类实现了Map接口的一些公共方法,以便将实现此接口所需的工作最小化。
AbstractMap类中实现的公共方法包括containsValue containsKey、get(Object key)、remove(Object key)等等,当然这些方法里面的部分实现也依赖于子类的某些方法。这种模式也叫做骨架模式,父抽象类制定了方法的部分骨架,具体实现由子类实现,这样多个子类可以有不同的实现。接下来看下HashMap类的细节。
HashMap其实就是一种数组链表的数据结构,数组是说不同hash的key放在一个entry[]数组里面,链表是指当key的hash相同时,HashMap采用的是链表法来处理hash冲突。这样HashMap就结合了数组和链表的优点。HashMap运行key、value为null。
上图就是HashMap的数据结构,每一个bucket都有一个entry。
/**
* Constructs an empty HashMap with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
看下构造方法, initialCapacity 表示初始容量, loadFactor表示加载因子,默认initialCapacity 为16, float loadFactor为0.75,当HashMap的实际长度超过initialCapacity*loadFactor时,为了避免过多的hash碰撞,HashMap就会进行扩容。代码如下
/**
* Adds a new entry with the specified key, value and hash code to
* the specified bucket. It is the responsibility of this
* method to resize the table if appropriate.
*
* Subclass overrides this to alter the behavior of put method.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
那么HashMap是怎样确定某个key应该放在哪个位置,其实是根据对key进行hash后,再对Entry
int i = indexFor(hash, table.length);
当key的hash冲突时,采用链头插入法将新的entry加入到hashMap,这样做是为了避免尾部遍历。
HashMap就暂时介绍到这里,当然HashMap存在并发问题,HashMap并不是一个线程安全的类,可以使用Collections.synchronizedMap(Map
http://www.cnblogs.com/andy-zhou/p/5402984.html