HashMap是一种常见的键值对存储数据的数据结构,它的工作原理可以简单概括为以下几个步骤:
-
哈希函数:当我们向HashMap中存入一个键值对时,首先会通过哈希函数将键映射到一个索引位置上。这个哈希函数将键转化为一个整数,这个整数就是该键值对在数组中的索引位置。
-
数组存储:HashMap内部使用一个数组来存储键值对。在对应索引位置上,将键值对存储在数组中。
-
冲突处理:由于哈希函数的结果可能会出现冲突,即多个键值对映射到了同一个索引位置上。为了解决冲突问题,HashMap使用了链表或红黑树的数据结构来存储多个键值对。
- 链表:当冲突发生时,新的键值对会被添加到链表的末尾。这样,从数组中的索引位置开始,通过遍历链表,即可找到对应的键值对。
- 红黑树:为了提高查找效率,当链表长度超过一定阈值(默认为8)时,链表会转化为红黑树存储方式。
- 查找和删除:当我们需要查找一个键值对时,首先使用哈希函数获得索引位置,然后遍历链表或红黑树,找到对应的键值对。当我们需要删除一个键值对时,也是通过查找找到对应的键值对,然后将其从链表或红黑树中删除。
总结起来,HashMap的工作原理是通过哈希函数将键映射到数组的索引位置上,解决冲突问题,并使用链表或红黑树来存储多个键值对。这样可以以常数时间复杂度O(1)进行插入、查找和删除操作,使HashMap成为一种高效的数据结构。
以下是一个简单的 HashMap 源码示例:
import java.util.LinkedList;class Entry {private Object key;private Object value;public Entry(Object key, Object value) {this.key = key;this.value = value;}public Object getKey() {return key;}public Object getValue() {return value;}
}public class HashMap {private int capacity;private LinkedList<Entry>[] buckets;public HashMap(int capacity) {this.capacity = capacity;this.buckets = new LinkedList[capacity];}public void put(Object key, Object value) {int index = getIndex(key);LinkedList<Entry> bucket = buckets[index];if (bucket == null) {bucket = new LinkedList<>();buckets[index] = bucket;}for (Entry entry : bucket) {if (entry.getKey().equals(key)) {entry.setValue(value);return;}}bucket.add(new Entry(key, value));}public Object get(Object key) {int index = getIndex(key);LinkedList<Entry> bucket = buckets[index];if (bucket != null) {for (Entry entry : bucket) {if (entry.getKey().equals(key)) {return entry.getValue();}}}return null;}public void remove(Object key) {int index = getIndex(key);LinkedList<Entry> bucket = buckets[index];if (bucket != null) {for (Entry entry : bucket) {if (entry.getKey().equals(key)) {bucket.remove(entry);return;}}}}private int getIndex(Object key) {int hashCode = key.hashCode();return hashCode % capacity;}
}
这是一个简化的 HashMap 的实现,使用数组和链表来存储键值对。它具有以下功能:
put(key, value)
:将给定的键值对添加到 HashMap 中。get(key)
:根据给定的键返回相应的值。remove(key)
:根据给定的键删除相应的键值对。
该实现使用哈希函数将键映射到数组索引。如果发生哈希冲突,即不同的键映射到相同的索引,它使用链表来解决冲突。每个数组索引都是一个链表,其中包含具有相同哈希码的键值对。
请注意,此实现仅用于演示目的。在实际应用中,Java 提供了更强大和高效的 HashMap 实现。