HashMap原理详解

HashMap原理详解

一、引言

在Java中,HashMap 是一个非常关键的数据结构,它提供了快速的查找、插入和删除操作。HashMap 的实现基于哈希表,它通过数组和链表(在JDK 1.8中为链表或红黑树)来解决哈希冲突。本文将详细探讨 HashMap 的基本构成、冲突解决机制以及在JDK 1.8中的优化。

二、基本构成

1、数组和链表/红黑树

HashMap 的核心是由数组组成的桶(bucket),每个桶存储一个链表(或红黑树)。当插入一个键值对时,HashMap 会根据键的哈希值找到对应的桶,然后将键值对插入到桶中的链表(或红黑树)。

1.1、数组

数组是 HashMap 的基础结构,它定义了 HashMap 的容量。数组的每个位置称为一个桶(bucket),用于存储键值对。

transient Node<K,V>[] table;
1.2、链表

当多个键的哈希值映射到同一个桶时,这些键值对会以链表的形式存储在该桶中。链表用于解决哈希冲突。

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
    
    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey() { ... }
    public final V getValue() { ... }
    public final V setValue(V newValue) { ... }
    public final boolean equals(Object o) { ... }
    public final int hashCode() { ... }
}
1.3、红黑树

在JDK 1.8中,当链表的长度超过一定阈值(默认为8)时,链表会被转换成红黑树,以提高搜索效率。

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // 父节点
    TreeNode<K,V> left;    // 左子树
    TreeNode<K,V> right;   // 右子树
    TreeNode<K,V> prev;    // 用于红黑树的前驱节点
    boolean red;           // 用于红黑树的颜色

    TreeNode(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

2、哈希函数

HashMap 使用键的 hashCode() 方法计算哈希值,然后通过哈希值和数组长度的位运算得到桶的索引。

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n, i, binCount;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[i = (n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((key == first.key) || (key != null && key.equals(first.key))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key, e);
            do {
                if (e.hash == hash &&
                    ((key == e.key) || (key != null && key.equals(e.key))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

三、冲突解决与性能优化

1、冲突解决

HashMap 通过链表(或红黑树)解决哈希冲突。当两个键的哈希值相同时,它们会被存储在同一个桶的链表(或红黑树)中。

2、性能优化

  • 扩容机制:当 HashMap 中的元素数量超过负载因子与当前容量的乘积时,HashMap 会进行扩容,通常是将容量翻倍。
if ((size >= threshold = (tab == null) ? DEFAULT_INITIAL_CAPACITY : MAXIMUM_CAPACITY))
    resize();
  • 红黑树:在JDK 1.8中,当链表长度超过阈值时,链表会被转换成红黑树,以优化搜索性能。

四、总结

HashMap 是Java中使用非常广泛的数据结构,它通过数组和链表(或红黑树)的组合提供了高效的数据存储和查询能力。理解其内部实现原理对于优化程序性能和解决实际问题具有重要意义。


版权声明:本博客内容为原创,转载请保留原文链接及作者信息。

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值