Java集合类
1.HashMap
源码分析:
put值操作:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
//初始化定义Node[],Node,初始化Node[]大小。 Node<K,V>[] tab; Node<K,V> p; int n, i;
//首次初始化,table=null if ((tab = table) == null || (n = tab.length) == 0)
//调用resize()进行初始化扩容,默认大小为16 n = (tab = resize()).length;
//判断上一步初始化所得Node(实质为数组)是否为空。首次创建为空,会执行此步骤,创建新的Node节点并保存数据<hash(key),key,value,next<指针>> if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null);
//若不是首次创建,执行此步骤。 else { Node<K,V> e; K k;
//hash(key),key 都相同且不为空,直接赋值 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p;
//红黑树赋值 else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else {
//遍历链表,获取next为空的Node并赋值 for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//此处并不一定会转化为红黑树 treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } }
//如果e不为空,即找到了一个去存储Key-value的Node if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
get值操作:
final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) {
//true,检测是否是TreeNode if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do {
//false,判断下一个节点是否是要查找的对象 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
HashMap的扩容机制
1 final Node<K,V>[] resize() {
2 Node<K,V>[] oldTab = table;
3 int oldCap = (oldTab == null) ? 0 : oldTab.length;
4 int oldThr = threshold;
5 int newCap, newThr = 0;
//容量大于0,说明不是第一次初始化
6 if (oldCap > 0) {
//超过最大容量:2^30
7 if (oldCap >= MAXIMUM_CAPACITY) {
//临界值等于Integer类型的最大值 0x7fffffff=2^31-1
8 threshold = Integer.MAX_VALUE;
9 return oldTab;
10 }
//当前容量在默认值和最大值的一半之间
11 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
12 oldCap >= DEFAULT_INITIAL_CAPACITY)
//新临界值为当前临界值的两倍
13 newThr = oldThr << 1; // double threshold
14 }
//当前容量为0,但是当前临界值不为0,让新的容量等于当前临界值
15 else if (oldThr > 0) // initial capacity was placed in threshold
16 newCap = oldThr;
//当前容量和临界值都为0,让新的容量为默认值,临界值=初始容量*默认加载因子
17 else { // zero initial threshold signifies using defaults
18 newCap = DEFAULT_INITIAL_CAPACITY;
19 newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
20 }
//如果新的临界值为0
21 if (newThr == 0) {
22 float ft = (float)newCap * loadFactor;
23 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
24 (int)ft : Integer.MAX_VALUE);
25 }
//临界值赋值
26 threshold = newThr;
27 @SuppressWarnings({"rawtypes","unchecked"})
//扩容table
28 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
29 table = newTab;
30 if (oldTab != null) {
31 for (int j = 0; j < oldCap; ++j) {
32 Node<K,V> e;
33 if ((e = oldTab[j]) != null) {
34 oldTab[j] = null;
35 if (e.next == null)
36 newTab[e.hash & (newCap - 1)] = e;
//节点为红黑树,进行切割操作
37 else if (e instanceof TreeNode)
38 ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
39 else {
//链表的下一个节点还有值,但节点位置又没有超过
//就是扩容后仍然在原地的元素链表
//就是扩容后下标为 原位置+原容量 的元素链表,从而不需要重新计算hash。
40 Node<K,V> loHead = null, loTail = null; 41 Node<K,V> hiHead = null, hiTail = null; 42 Node<K,V> next;
//循环链表直到链表末再无节点 43 do { 44 next = e.next;
//e.hash&oldCap == 0 判断元素位置是否还在原位置 45 if ((e.hash & oldCap) == 0) { 46 if (loTail == null) 47 loHead = e; 48 else 49 loTail.next = e; 50 loTail = e; 51 } 52 else { 53 if (hiTail == null) 54 hiHead = e; 55 else 56 hiTail.next = e; 57 hiTail = e; 58 } 59 } while ((e = next) != null);
//循环链表结束,通过判断loTail是否为空来拷贝整个链表到扩容后table 60 if (loTail != null) { 61 loTail.next = null; 62 newTab[j] = loHead; 63 } 64 if (hiTail != null) { 65 hiTail.next = null; 66 newTab[j + oldCap] = hiHead; 67 } 68 } 69 } 70 } 71 } 72 return newTab; 73 }
解决hash冲突的方法以及HashMap解决hash冲突的方法