Java集合类HashMap源码解析

Note:

HashMap继承自AbstractMap类,实现了Map接口,Cloneable接口,Serializable接口。AbstractMap类是个抽象类,定义了Map最常用的方法,可以看做是接口Map的最小类实现。HashMap是基于哈希表实现的,而另一个Map接口实现类TreeMap是基于红黑树的。

以下是对部分源码的解析:

1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 初始容量
2 static final int MAXIMUM_CAPACITY = 1 << 30; // 最大容量
3 static final float DEFAULT_LOAD_FACTOR = 0.75f;  
// 装载因子,当元素数量为总容量的75%时,需要扩大容量,重散列
4 static final int TREEIFY_THRESHOLD = 8;  // 即使用树结构代替链表表示每个桶的阈值数 5 static final int UNTREEIFY_THRESHOLD = 6;  // 在resize过程中,不使用树结构的阈值数 6 static final int MIN_TREEIFY_CAPACITY = 64;  //

对于每个HashMap中的每个桶有如下定义:

 // 静态内部类不能访问外部类的实例成员(因为静态成员不能访问非静态成员)
1
static class Node<K,V> implements Map.Entry<K,V> {  // 语法:可以实现接口中的内部接口 2 final int hash;  // final的成员变量必须在非静态初始化块,声明该变量,构造器中赋初值 3 final K key; 4 V value; 5 Node<K,V> next; 6 7 Node(int hash, K key, V value, Node<K,V> next) { 8 this.hash = hash; 9 this.key = key; 10 this.value = value; 11 this.next = next; 12 } 13 14 public final K getKey() { return key; } 15 public final V getValue() { return value; } 16 public final String toString() { return key + "=" + value; } 17 18 public final int hashCode() { 19 return Objects.hashCode(key) ^ Objects.hashCode(value);  
            // 使用Objects.hashCode来计算每个成员的hashCode
20 } 21 22 public final V setValue(V newValue) { 23 V oldValue = value; 24 value = newValue; 25 return oldValue; 26 } 27 28 public final boolean equals(Object o) { 29 if (o == this) 30 return true; 31 if (o instanceof Map.Entry) { 32 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 33 if (Objects.equals(key, e.getKey()) && 34 Objects.equals(value, e.getValue()))  
              // 使用Objects.equals来比较每个成员
35 return true; 36 } 37 return false; 38 } 39 }

下面是类成员的声明:

1 transient Node<K,V>[] table;  // 声明一个表,表的类型是一对(K,V)
2 transient Set<Map.Entry<K,V>> entrySet;  // (K,V)对的集合
3 transient int size;  // 哈希表中的(K,V)对的个数
4 transient int modCount;  // 对哈希表的修改次数
5 int threshold;  // 要扩容时元素个数的阈值(capacity * load factor)
6 final float loadFactor;  // 装载因子

下面是构造器的定义:

构造器一:

 1 public HashMap(int initialCapacity, float loadFactor) {
 2         if (initialCapacity < 0)
 3             throw new IllegalArgumentException("Illegal initial capacity: " +
 4                                                initialCapacity);
 5         if (initialCapacity > MAXIMUM_CAPACITY)
 6             initialCapacity = MAXIMUM_CAPACITY;
 7         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 8             throw new IllegalArgumentException("Illegal load factor: " +
 9                                                loadFactor);
10         this.loadFactor = loadFactor;
11         this.threshold = tableSizeFor(initialCapacity);
12     }

使用指定的初始容量和装载因子来初始化HashMap,注意源码中会根据用户的initialCapacity将threshold转换成2的幂次大小,下面是tableSizeFor的定义:

1 static final int tableSizeFor(int cap) {
2         int n = cap - 1;
3         n |= n >>> 1;  // 无符号右移,高位补0
4         n |= n >>> 2;
5         n |= n >>> 4;
6         n |= n >>> 8;
7         n |= n >>> 16;
8         return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
9     }

 

posted @ 2016-10-02 20:49  传奇魔法师  阅读(121)  评论(0编辑  收藏  举报