返回

深入HashMap源码,剖析每行代码,不再是黑箱!

后端

在软件开发的世界里,数据结构和算法是至关重要的基石,它们就像搭积木一样,构成了应用程序的基本组成部分。在这其中,HashMap以其强大的功能和广泛的应用,成为程序员的宠儿。

HashMap是一种基于哈希表的数据结构,它以键值对的形式存储数据,键可以是任意对象,值也可以是任意对象。HashMap的强大之处在于,它可以通过键值对的形式快速检索数据,而无需遍历整个数据集合。

今天,我们就将深入HashMap的源码,手把手带你剖析每一行代码,让你对HashMap的底层实现原理了如指掌。

首先,我们先来了解一下HashMap的基本结构。HashMap内部由一个数组和一个链表组成,数组中的每个元素都是一个链表的头部,链表中的每个元素都是一个键值对。

public class HashMap<K, V> {

    private Entry<K, V>[] table;

    // ... 其他代码
}

HashMap的数组称为“哈希表”,每个数组元素称为“桶”。桶是链表的头部,链表中的每个元素称为“节点”。

当向HashMap中添加一个键值对时,HashMap会首先根据键的哈希值计算出桶的索引,然后将键值对添加到对应的桶中。如果桶中已经有数据,那么就将键值对添加到桶中的链表中。

public V put(K key, V value) {
    int hash = key.hashCode();
    int index = hash % table.length;

    Entry<K, V> entry = new Entry<>(key, value);

    // 如果桶中没有数据,则直接将键值对添加到桶中
    if (table[index] == null) {
        table[index] = entry;
        return null;
    }

    // 如果桶中已有数据,则将键值对添加到桶中的链表中
    Entry<K, V> current = table[index];
    while (current.next != null) {
        current = current.next;
    }
    current.next = entry;

    return null;
}

当从HashMap中获取一个值时,HashMap会首先根据键的哈希值计算出桶的索引,然后在对应的桶中搜索键值对。如果桶中没有数据,那么就说明HashMap中没有这个键值对。如果桶中已有数据,那么就遍历桶中的链表,直到找到与键匹配的键值对。

public V get(K key) {
    int hash = key.hashCode();
    int index = hash % table.length;

    Entry<K, V> entry = table[index];

    // 如果桶中没有数据,则说明HashMap中没有这个键值对
    if (entry == null) {
        return null;
    }

    // 如果桶中已有数据,则遍历桶中的链表,直到找到与键匹配的键值对
    while (entry != null) {
        if (entry.key.equals(key)) {
            return entry.value;
        }
        entry = entry.next;
    }

    return null;
}

当从HashMap中删除一个键值对时,HashMap会首先根据键的哈希值计算出桶的索引,然后在对应的桶中搜索键值对。如果桶中没有数据,那么就说明HashMap中没有这个键值对。如果桶中已有数据,那么就遍历桶中的链表,直到找到与键匹配的键值对,然后将其从链表中删除。

public V remove(K key) {
    int hash = key.hashCode();
    int index = hash % table.length;

    Entry<K, V> entry = table[index];

    // 如果桶中没有数据,则说明HashMap中没有这个键值对
    if (entry == null) {
        return null;
    }

    // 如果桶中已有数据,则遍历桶中的链表,直到找到与键匹配的键值对
    Entry<K, V> previous = null;
    while (entry != null) {
        if (entry.key.equals(key)) {
            if (previous == null) {
                // 如果键值对位于链表的头部,则将头指针指向下一个节点
                table[index] = entry.next;
            } else {
                // 如果键值对位于链表的中间或尾部,则将前一个节点的next指针指向下一个节点
                previous.next = entry.next;
            }
            return entry.value;
        }
        previous = entry;
        entry = entry.next;
    }

    return null;
}

通过剖析HashMap的源码,我们对HashMap的底层实现原理有了更深入的了解。HashMap的强大之处在于,它可以通过键值对的形式快速检索数据,而无需遍历整个数据集合。这种特性使得HashMap在各种场景中都得到了广泛的应用,比如缓存、路由、索引等。

希望这篇深度剖析文章能够帮助你更好地理解HashMap的底层实现原理,并在你的项目中灵活运用HashMap。