在 JDK 1.8 中,HashMap
是一个常用的实现了 Map
接口的哈希表,它允许存储键值对,并且键和值都可以为 null。HashMap
的主要特点是其基于哈希表的实现,提供了快速的查找和插入操作。以下是 HashMap
中 get
和 put
方法的介绍及其实现细节:
put
方法
put
方法用于将指定的键值对插入到 HashMap
中。如果该键已经存在,则更新对应的值。
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
hash(key)
:计算键的哈希值。putVal
:执行插入操作,参数包括计算出的哈希值、键、值等。
putVal
方法的主要流程:
- 计算键的哈希值。
- 根据哈希值找到对应的桶(bucket)。
- 如果桶为空,则创建一个新的节点放入桶中。
- 如果桶不为空,则遍历桶中的链表(或树结构):
- 如果找到相同的键,则更新值。
- 如果没有找到,则在链表尾部插入新节点或将链表转换为树结构后插入新节点。(JDK1.8之前是头插法,可能导致循环链表)
在 JDK 1.8 中,当链表长度超过阈值(默认为 8)时,链表会转换为红黑树结构以提高性能。
get
方法
get
方法用于根据键获取对应的值。如果键不存在,则返回 null。
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
hash(key)
:计算键的哈希值。getNode
:根据哈希值和键查找对应的节点。
getNode
方法的主要流程:
- 计算键的哈希值。
- 根据哈希值找到对应的桶。
- 如果桶为空,则返回 null。
- 如果桶不为空,则遍历桶中的链表(或树结构):
- 如果找到相同的键,则返回对应的值。
- 如果没有找到,则继续查找下一个节点,直到找到或遍历完所有节点。
HashMap
的一些关键点
- 容量和负载因子:
HashMap
有一个初始容量和负载因子。当哈希表中元素的数量超过容量与负载因子的乘积时,哈希表会进行扩容(rehashing)。 - 红黑树:在 JDK 1.8 中,当链表长度超过一定阈值(默认为 8)时,链表会转换为红黑树以提高查找和插入的性能。
- 哈希冲突:当不同的键有相同的哈希值时,会发生哈希冲突。
HashMap
使用链表和红黑树来解决哈希冲突。
HashMap
示例
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
// 使用 put 方法插入键值对
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
// 使用 get 方法根据键获取值
System.out.println("Value for key 'one': " + map.get("one")); // 输出 1
System.out.println("Value for key 'four': " + map.get("four")); // 输出 null
// 更新键 "one" 的值
map.put("one", 10);
System.out.println("Updated value for key 'one': " + map.get("one")); // 输出 10
}
}
这个示例展示了如何使用 HashMap
的 put
和 get
方法插入和获取键值对。