JAVA集合三Map—— HashMap源码分析
*特别声明:
*本文分析基于JDK8
*转载请注明源地址。
主要下面几个方法来了解HashMap
1、HashMap的数据结构(存储结构)
2、Hash算法
3、冲突解决
4、扩容
5、存取
下图中包含了比较常用的Map接口的实现类。
一、Map的结构
Map是一种用来保存key-value的数据结构。Map接口提供了存取key和value的方法,并且提供了内部存储的数据结构接口Map/Entry<K,V>.
interface Entry<K,V> {
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
K getKey();}
接口提供了各种方法,需要自己去实现。所有的Map都是基于如此。
二、HashMap基本概念
在了解HashMap之前,可以去了解下Hash算法的概念,对理解HashMap很有帮助。
如果要设计保存key-value的结构,我们可以在每次put的时候,循环整个数组计算key是否重复,然后进行操作。get的时候也可以循环取出数据。这当然是可行的。但是如果数量很大的时候,自然会很慢,不是一种好的方法。
HashMap提供了基于hash算法的快速存取的Map结构。实现了Map接口,继承于AbstractMap。HashMap通过自己的Hash算法(通过Hashcode计算数组index,后面介绍),将key值计算为数组的索引位置,这样可以实现快速的存取。当然Hash算法可能会导致冲突。Hash值可能一样,计算出的索引位置也可能一样。这种情况我们称之为Hash冲突。
这种情况下,HashMap通过链表来解决Hash冲突。当复数key出现在相同的index位置后面,将会形成在该位置形成一个链表结构来存储。具体后续讲解。
三、数据结构
HashMap中通过数组和指针来保存数据。当然几乎所有JAVA的类都可以如此使用。HashMap实际是一个链表散列。如下图(网上下载的图)
HashMap中几个重要的个概念和结构。
//对象存储的table
transient Node<K,V>[] table;
//最大负载数量
int threshold;
//负载因子
final float loadFactor;
//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;