java hashmap put_[Java 8 HashMap 详解系列]3.HashMap 的 put() 方法执行原理

[Java 8 HashMap 详解系列] 文章目录

3.HashMap 的 put() 方法执行原理

HashMap 重要成员变量:

//初始值,为16,必须为2的次幂

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

//当容量被占满0.75时就需要reSize扩容

static final float DEFAULT_LOAD_FACTOR = 0.75f;

//链表长度到8,就转为红黑树

static final int TREEIFY_THRESHOLD = 8;

// 树大小为6,就转回链表

static final int UNTREEIFY_THRESHOLD = 6;

HashMap类中有一个非常重要的字段,就是Node[] table,即哈希桶数组:

/**

* The table, initialized on first use, and resized as

* necessary. When allocated, length is always a power of two.

* (We also tolerate length zero in some operations to allow

* bootstrapping mechanics that are currently not needed.)

*/

transient Node[] table;

Node是HashMap的一个内部类,实现了Map.Entry接口,本质就是一个映射(键值对) :

/**

* Basic hash bin node, used for most entries. (See below for

* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)

*/

static class Node implements Map.Entry {

final int hash;

final K key;

V value;

Node next;

Node(int hash, K key, V value, Node next) {

this.hash = hash;

this.key = key;

this.value = value;

this.next = next;

}

public final K getKey() { return key; }

public final V getValue() { return value; }

public final String toString() { return key + "=" + value; }

public final int hashCode() {

return Objects.hashCode(key) ^ Objects.hashCode(value);

}

public final V setValue(V newValue) {

V oldValue = value;

value = newValue;

return oldValue;

}

public final boolean equals(Object o) {

if (o == this)

return true;

if (o instanceof Map.Entry) {

Map.Entry,?> e = (Map.Entry,?>)o;

if (Objects.equals(key, e.getKey()) &&

Objects.equals(value, e.getValue()))

return true;

}

return false;

}

}

9f8dd0843c49

/**

* Associates the specified value with the specified key in this map.

* If the map previously contained a mapping for the key, the old

* value is replaced.

*

* @param key key with which the specified value is to be associated

* @param value value to be associated with the specified key

* @return the previous value associated with key, or

* null if there was no mapping for key.

* (A null return can also indicate that the map

* previously associated null with key.)

*/

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

/**

* Implements Map.put and related methods

*

* @param hash hash for key

* @param key the key

* @param value the value to put

* @param onlyIfAbsent if true, don't change existing value

* @param evict if false, the table is in creation mode.

* @return previous value, or null if none

*/

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

boolean evict) {

Node[] tab; Node p; int n, i;

//1.初始化

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

//2.当前位置没有存储节点,则直接插入节点

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

else {

Node e; K k;

//3.hash 相等 && key 相等

if (p.hash == hash &&

((k = p.key) == key || (key != null && key.equals(k))))

e = p;

//4.节点插入红黑树

else if (p instanceof TreeNode)

e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);

else {

//5.遍历链表

for (int binCount = 0; ; ++binCount) {

//如果到了链表尾部:(e = p.next) == null

if ((e = p.next) == null) {

//节点插入链表尾部

p.next = newNode(hash, key, value, null);

//如果节点个数>=TREEIFY_THRESHOLD,链表结构转为红黑树结构

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

treeifyBin(tab, hash);

break;

}

// 找到了对应元素,就可以停止了, break

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

//继续遍历链表的下一个节点

p = e;

}

}

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;

}

链表转成红黑树的操作 treeifyBin(tab, hash) 我们将在

详细讲解.

Kotlin 开发者社区

9f8dd0843c49

国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。

越是喧嚣的世界,越需要宁静的思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值