探秘Java HashMap:背后的魔法与疯狂
本文最后更新于83 天前,其中的信息可能已经过时,如有错误请发送邮件到sherry.rain@qq.com

第一部分:底层魔法

首先,让我们揭开HashMap的神秘面纱。它的底层实现其实是一个数组,不过这个数组里面装的不是普通的元素,而是一种叫做“桶”的东西。听起来有点像魔法道具吧?没错,它的确是HashMap的魔法之一。

每个桶里面都存放着一个键值对,也就是我们常说的Entry。这个Entry是由键和值组成的,就好像是一对魔法师和他的宠物一样,紧密相连。当我们根据键来查找值的时候,HashMap会利用魔法算法找到相应的桶,然后从里面取出对应的值。简直就像是从帽子里面抽出兔子一样神奇!

让我们来看一段源码,感受一下HashMap的神奇之处:

public V get(Object key) {
    if (key == null)
        return getForNullKey();
    int hash = hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
            return e.value;
    }
    return null;
}

这段代码展示了HashMap中的get方法,它通过计算键的哈希值,找到对应的桶,并遍历链表或红黑树来查找值。是不是感觉有点像在探寻宝藏的过程呢?

第二部分:数据结构狂欢

现在我们来聊聊HashMap的数据结构。除了那个神奇的数组,HashMap还使用了链表和红黑树这两种数据结构。是不是觉得这里有点小小的疯狂?别担心,我会为你揭开其中的奥秘。

当我们往HashMap中添加元素的时候,它会根据键的哈希值来决定放在哪个桶里。如果发生了哈希碰撞,也就是两个键的哈希值相同,HashMap会将它们放在同一个桶里,并使用链表将它们串联起来。这就好像是一条神奇的魔法链,将不同的键值对有序地连接在一起。

但是,如果链表中的元素过多,为了提高效率,HashMap会将链表转换成红黑树。这个红黑树就像是一把能自动平衡的魔法剑,可以在查找时提供更快的速度。当然,如果红黑树的元素数量减少到一定程度,它又会变回链表。是不是感觉像是在玩一场数据结构的狂欢派对呢?

让我们再来看一段源码,感受一下HashMap的数据结构之奇妙:

final Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
    return new Node<>(hash, key, value, next);
}

final TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
    return new TreeNode<>(hash, key, value, next);
}

这段代码展示了HashMap中创建新的节点和创建新的红黑树节点的方法。通过这些数据结构,HashMap能够高效地存储和查找键值对。是不是感觉自己成了一个魔法师,掌握着神秘的数据结构魔法呢?

第三部分:扩容机制的魔法

最后,我们来看看HashMap的扩容机制。当HashMap中的元素数量超过了负载因子(默认为0.75)乘以数组大小时,它会触发扩容操作。这就好像是魔法师的袍子无限延伸一样,HashMap会创建一个新的更大的数组,并将原来的元素重新分配到新的桶里面。

让我们再来看一段源码,感受一下HashMap的扩容机制:

void resize(int newCapacity) {
    Node<K,V>[] oldTab = table;
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    if (oldCap > 0 && newCapacity > oldCap) {
        Node<K,V>[] newTab = new Node[newCapacity];
        transfer(newTab);
        table = newTab;
    }
}

void transfer(Node<K,V>[] newTab) {
    Node<K,V>[] oldTab = table;
    int newCap = newTab.length;
    for (int j = 0; j < oldTab.length; ++j) {
        Node<K,V> e;
        if ((e = oldTab[j]) != null) {
            oldTab[j] = null;
            if (e.next == null)
                newTab[e.hash & (newCap - 1)] = e;
            else if (e instanceof TreeNode)
                ((TreeNode<K,V>)e).split(this, newTab, j, oldTab);
            else {
                Node<K,V> loHead = null, loTail = null;
                Node<K,V> hiHead = null, hiTail = null;
                Node<K,V> next;
                do {
                    next = e.next;
                    if ((e.hash & oldCap) == 0) {
                        if (loTail == null)
                            loHead = e;
                        else
                            loTail.next = e;
                        loTail = e;
                    } else {
                        if (hiTail == null)
                            hiHead = e;
                        else
                            hiTail.next = e;
                        hiTail = e;
                    }
                } while ((e = next) != null);
                if (loTail != null) {
                    loTail.next = null;
                    newTab[j] = loHead;
                }
                if (hiTail != null) {
                    hiTail.next = null;
                    newTab[j + oldCap] = hiHead;
                }
            }
        }
    }
}

这段代码展示了HashMap中的扩容操作。在resize方法中,HashMap会创建一个新的数组,并调用transfer方法将原来的元素重新分配到新的桶中。通过这种方式,HashMap能够保持高效率,即使在容量不足时也能正常工作。

总结: 通过这篇博客,我们深入探索了Java HashMap的底层实现、数据结构和扩容机制。HashMap就像是一个充满魔法与疯狂的世界,它利用数组、链表和红黑树等数据结构,以及扩容机制来保证高效的操作。无论你是新手还是老手程序员,相信在这段有趣的旅程中,你已经对HashMap有了更深入的了解。

希望这篇博客能够带给你一些乐趣和启发,让你对Java中的HashMap有更多的兴趣。如果你想要进一步探索,不妨阅读JDK源码,深入研究HashMap的实现细节。相信在这个魔法与疯狂的世界中,你会发现更多有趣的事情!

谢谢大家的阅读,如果你有任何问题或者想法,欢迎在下方留言与我交流。祝你编程愉快!

作者:Sry0
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议。转载请注明文章地址及作者
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇