HashMap详解以及常见面试题

HashMap详解以及常见面试题

强烈建议!!!阅读另外一篇用图演示流程的HashMap详解文章,不懂来敲我
点这里 >> 【多图预警,不懂来敲我】HashMap详解

一、概要

本文先会将hashmap的基本概念属性梳理一遍后,再从增删改查方法中每个步骤逐一解释说明。力求达到通熟易懂,逻辑清晰,便于加深印象。

二、概念

首先Hashmap的底层数据结构是由数组+链表组成的,是线程不安全,允许key和value为null。底层结构数组叫哈希桶,而桶内则是链表,链表中的节点Node存放着实际的元素。

Hashmap中获取元素时的主要流程步骤为,首先对key值进行hash算法得出hash值即哈希桶中的索引值,再找到对应的hash桶。如果存在,则通过(拉链法)链表从前往后比较value值是否相等,直到找到元素或下个节点为null时。
而增加元素或修改元素的主要流程步骤与获取相类似,不同在于当增加元素后,如果总元素size大于阈值时,会发生扩容。
在JDK8中,加强了hash算法的效率以及利用率,当桶内元素大于8和桶数组长度大于64时,将链表转换为红黑树,优化了扩容时的算法。

三、分解

1. hash算法

在上面概念中讲到,hash算法是计算key值对应哈希桶的位置即索引值。我们都知道数组在获取元素会比链表快,所以我们应该尽量让每个哈希桶只有一个元素,这样在查询时就只需要通过索引值找到对应的哈希桶内的值,而不需要再通过桶内的链表一个一个去查。所以hash算法的作用是为了让元素分散均匀,从而提高查询效率。那接下来通过代码来一步一步分析时如何让元素分布均匀的。

//这是根据key值获取value值的方法
public V get(Object key) {
    Node<K,V> e;
    //先调用hash(key)
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

//Hash算法如下
static final int hash(Object key) {
    int h;
    //第一步:先获取key中的hashCode值
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    //第二步 再与hashcode无符号向右移16位的值进行抑或 
}
final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        //第三步 n是指数组长度,hash与(n-1)进行&与运算
        (first = tab[(n - 1) & hash]) != null) {
        //省略
        ...
        ...
    }
    return null;
}

首先第一步获取hashcode没什么问题,到第二步为什么会跟hashcode无符号右移16位的值进行抑或呢? 其实是将高位与低位进行与运算,减少碰撞机率。第三步取余运算,但在计算机运算中&肯定比%快,又因为h % n = h &(n - 1),所以最终将第二步得到的hash跟n-1进行与运算。n是table中的长度。
hash算法图解

2、get方法,查询元素

查询get方法相对简单,只要明白hash算法后得到哈希桶的索引值,再对桶内的链表进行比较hash,key是否相等。下面是get方法中主要的代码

    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        //如果表为null或长度为0,或者经过hash算法后得到的哈希桶为null,则直接返回null
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            //如果链表中的第一个节点元素相等则直接返回该Node
            if (first.hash == hash && // always check first node
                ((k = firs
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值