常用属性
1 | static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //默认大小16 |
get
1 | public V get(Object key) { |
对Key进行hash后,调用getNode()方法
1 | final Node<K,V> getNode(int hash, Object key) { |
first = tab[(n - 1) & hash] :通过key的hash值定位到这个元素在数组的为位置first
在判断首节点是不是要查找的内容。
1 | //判断是否为查找对象的方法:先比较hash值,然后key相等或者key的equal方法相等 |
接着判断Node的类型是不是TreeNode,如果是调用getTreeNode(hash, key)方法。
否则遍历Node节点,进行查找。否则返回null。
看一下TreeNode的查找方法:getTreeNode(hash, key)
1 | final TreeNode<K,V> getTreeNode(int h, Object k) { |
这个方法是来找到TreeNode的根节点,也就是parent为空的节点
1 | final TreeNode<K,V> find(int h, Object k, Class<?> kc) { |
判断当前节点的hash值比key的hash大,从左节点查找。查找成功的条件hash值相等,然后判断key相等或者key的equal方法相等。和Node的条件是一样的。找不到放回null
put
1 | public V put(K key, V value) { |
和get方法一样,也对key重新hash了,接着调用了putVal()方法。
1 | final V putVal(int hash, K key, V value, boolean onlyIfAbsent, |
put方法:如果节点Node就新建一个节点,Node如果和put的key符合相等条件,则覆盖该Node。如果Node的长度为7,新建一个Node后,就会被树化。树化的过程比较复杂。
1 | static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { |
resize
1 | final Node<K,V>[] resize() { |
table为null,容量为16,负载因子为0.75。否则:如果原始容量的size的两倍大于16,则容器为原来的两倍,threshold为原来的两倍。否则容量为两倍,threshold不变。然后用新的容量构建数组和链表。