夫唯不争,故天下莫能与之争

简介源码分析

HashMap是JAVA抽象出来存储键值对的集合,它的底层是哈希表,有哈希表就会有冲突,所以HashMap用单链表解决冲突,也就是拉链法。 HashMap是不安全的,在多线程的环境下可用ConcurrentHashMap,或者利用Collections工具类中的同步方法。

先不急于说明其他的,我们先来分析一下单链表的构造

static class Entry<K,V> implements Map.Entry<K,V> {final K key;//存放键值对的键V value; //存放值Entry<K,V> next;hash; //存放hash值/*** 创建一个新的entry*/Entry(int h, K k, V v, Entry<K,V> n) {value = v;next = n;key = k;hash = h;}public final K getKey() {return key;}public final V getValue() {return value;}V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}(Object o) {if (!(o instanceof Map.Entry))return false;Map.Entry e = (Map.Entry)o;Object k1 = getKey();Object k2 = e.getKey();//如果两个的键和值都相等才会返回trueif (k1 == k2 || (k1 != null && k1.equals(k2))) {Object v1 = getValue();Object v2 = e.getValue();if (v1 == v2 || (v1 != null && v1.equals(v2)))return true;}return false;}() {return (key==null ? 0 : key.hashCode()) ^(value==null ? 0 : value.hashCode());}public final String toString() {return getKey() + “=” + getValue();}//当向HashMap中put键值对时,如果对应的键已经存在,则会调用此函数void recordAccess(HashMap<K,V> m) {}//当删除HashMap中的某个值时,会调用此函数void recordRemoval(HashMap<K,V> m) {}}

接着我们来看看几个比较重要的成员变量

   //默认的初始容量,注意到是2的幂   DEFAULT_INITIAL_CAPACITY = 16;   //默认最大容量,2的30次方   MAXIMUM_CAPACITY = 1 << 30;   // 默认的加载因子   DEFAULT_LOAD_FACTOR = 0.75f;  //存放单链表头结点的哈希数组   transient Entry[] table;   //实际存放的值   transient int size;   //HashMap的阈值,如果超出阈值,则需要扩容(加载因子*容量)   int threshold;   /*加载因子的实际大小加载因子是表示Hash表中元素的填满的程度   加载因子越大,填满的元素越多,好处是空间利用率高了,但冲突大了,链表很长,查找效率低;加载因子越小,填满的元素就越小,冲突小了,但是空间却浪费了。一般不设置*/   final float loadFactor;   //HashMap被修改的次数   modCount;

这里提到了HashMap的容量是2的幂,当然还有数组的长度也必须为2的幂,稍后我们会说明这一点。

接下来是构造函数,HashMap一共有四个构造函数,,我们来逐一分析:

public HashMap(int initialCapacity, float loadFactor) {//容量小于0会抛出异常if (initialCapacity < 0)throw new IllegalArgumentException(“Illegal initial capacity: ” + initialCapacity);//如果初始化的容量大于默认的最大容量,则用其替换if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;//加载因子小于0,或者是一个NaN会抛出异常if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException(“Illegal load factor: ” +loadFactor);//找到大于指定容量的最小的2次幂int capacity = 1;while (capacity < initialCapacity)capacity <<= 1;this.loadFactor = loadFactor;//边界等于容量*加载因子threshold = (int)(capacity * loadFactor);//初始化哈希数组table = new Entry[capacity];init();}(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);}() {this.loadFactor = DEFAULT_LOAD_FACTOR;threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);table = new Entry[DEFAULT_INITIAL_CAPACITY];init();}(Map<? extends K, ? extends V> m) {this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);putAllForCreate(m);}

计算hash值和数组的索引位置

hash(int h) {h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);} static int indexFor(int h, int length) {return h & (length-1);}总在盼望未来,愿你的人生美开

夫唯不争,故天下莫能与之争

相关文章:

你感兴趣的文章:

标签云: