HashMap源码浅析

本文摘要

HashMap是Java集合中使用频率很高的一种用于键值对映射数据结构,在很多场景都有着广泛的应用。
本文将着重介绍HashMap在JDK1.8中的实现。

HashMap简介

下图为HashMap继承和实现结构图。我们可以发现,HashMap继承了抽象类AbstractMap,实现了Map接口,除此之外,它实现了Cloneable,Serializable接口,说明HashMap可以实现复制和序列化。
在这里插入图片描述

HashMap的基本结构

底层结构概述

HashMap的基本思想就是利用Hash函数将数据分散地放置在不同的位置;在查询时,再次使用Hash函数算出数据所在的位置,从而快速的查找到数据;但是这又有可能出现不同的数据出现在相同的位置(Hash冲突),这就需要仔细设计如何在有Hash冲突的情况下,还能让查询有着较高的效率。
在Java中,不同的JDK版本,HashMap在解决Hash冲突上存在的差别。
JDK1.7:HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。
JDK1.8:HashMap由数组+链表+红黑树组成的,数组是HashMap的主体,链表和红黑树则是主要为了解决哈希冲突而存在的。当链表长度超过某个长度(默认为8)和数组长度超过某个长度(默认为64)时,链表会转变成红黑树(为了提高查找的效率与性能)。
在这里插入图片描述

底层结构主体——table数组

HashMap的主干是一个Node数组,也可以叫做桶。

  // HashMap的主干数组,可以看到就是一个Node数组,初始值为空数组{},主干数组的长度一定是2的次幂。
  transient Node<K,V>[] table;

Node是HashMap的基本组成单元,每一个Node包含一个key-value键值对。(其实所谓Map其实就是保存了两个对象之间的映射关系的一种集合)

  static class Node<K,V> implements Map.Entry<K,V> {
   
        // 对key的hashcode值进行hash运算后得到的值
        final int hash;
        // 该节点的key值
        final K key;
        // 该节点的value值
        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;
        }
    }

HashMap的几个重要成员变量

成员变量名称 解释
DEFAULT_INITIAL_CAPACITY 默认初始大小(16)
MAXIMUM_CAPACITY 最大容量(2的30次方)
DEFAULT_LOAD_FACTOR 默认负载因子(0.75f)
TREEIFY_THRESHOLD 链表转换为红黑树的桶上节点数临界值(8)
UNTREEIFY_THRESHOLD 红黑树转换为链表的桶上节点数临界值(6)
size 存放元素的个数
threshold 阈值(临界值)
loadFactor 负载因子

1、这里我们首先要区分CAPACITY和size这两个变量:
①CAPACITY是指HashMap的容量,即数组的长度(桶的数量)
②size是指HashMap内部真正存储的数据数量
2、loadFactor负载因子
负载因子是用来衡量 HashMap 满的程度,表示HashMap的疏密程度
如果其数值过大,就表明当前HashMap比较拥挤,之后再向HashMap加入数据时,发生Hash冲突的概率会增大。
3、threshold阈值
threshold=容量(capacity)× 负载因子(loadFactor)
当HashMap的实际大小超过临界值时,会进行扩容,以减小HashMap增加数据时Hash冲突的概率。

HashMap的初始化(构造函数)

HashMap共有四个构造函数
1、带有默认初始容量(initialCapacity)和负载因子(loadFactor)的构造函数

public HashMap(int initialCapacity, float loadFactor) {
   
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

2、带有默认初始容量(initialCapacity)的构造函数

public HashMap(int
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值