【Map篇】HashMap详解

HashMap是Java中常用的线程不安全的键值对数据结构,基于哈希表实现,提供O(1)的平均查找、插入和删除效率。本文详细介绍了HashMap的成员变量、构造函数、put、remove、get方法的源码分析,以及resize过程。在多线程环境下,HashMap可能导致数据不一致,可使用ConcurrentHashMap确保线程安全。
摘要由CSDN通过智能技术生成


在这里插入图片描述

一. 简介

HashMap是Java中常用的数据结构之一,它是基于哈希表实现的,用于存储管理键值对。HashMap内部是由一个Entry数组和一个链表组成的,数组用于存储数据,链表用于解决哈希冲突。HashMap会根据实际需要,动态地调整数组的长度,以保证高效的查找、插入和删除操作。
在这里插入图片描述
其主要特点包括:

  • 高效性:HashMap内部采用哈希表实现,查找和插入操作的时间复杂度是O(1),具有高效性。
  • 线程不安全:HashMap是非线程安全的,如果多个线程同时并发访问同一个HashMap对象,可能会出现数据不一致的情况。
  • 支持null键和null值:HashMap允许键和值为null,但是需要注意,在使用时要特别小心,避免空指针异常。
  • 无序性:HashMap中键值对的存储是无序的,与添加顺序无关。

总之,HashMap是一种高效的数据存储和查找结构,它在Java中得到广泛应用,特别是在缓存、索引、状态跟踪等领域。
在这里插入图片描述

二. 源码分析

基于JDK1.8版本

1. 成员变量属性

 /**
  * 默认初始容量(必须是2的幂次方)
  * 指的是HashMap内部数组的大小
  */
 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

 /**
  * 最大容量,如果任何一个带参数的构造函数隐式指定了更高的值,则使用该容量
  * 必须是2的幂次方,最大不能超过1073741824
  */
 static final int MAXIMUM_CAPACITY = 1 << 30;

 /**
  * 构造函数中未指定时使用的负载系数
  * 指的是当HashMap内部数组的元素个数达到数组大小与负载因子的乘积时,会自动扩容
  */
 static final float DEFAULT_LOAD_FACTOR = 0.75f;

/**
 * 红黑树转成链表的长度阀值
 * 当链表的长度小于6时,此时的红黑树会重新转换成链表结构
 */
 static final int UNTREEIFY_THRESHOLD = 6;

 /**
  * 链表转化成红黑数的长度阈值
  * 当数组的长度大于等于64,且链表的长度大于8时,链表转红黑树
  */
 static final int TREEIFY_THRESHOLD = 8;

 /**
  * 将链表转话为红黑树的数组长度阀值
  */
 static final int MIN_TREEIFY_CAPACITY = 64;
 
 /**
  * 哈希桶,可以理解就是数组
  * 数组上存放的元素是Node<K,V>
  */
 transient Node<K,V>[] table;

2. 构造函数

创建一个空的HashMap,默认初始化大小为16,负载因子为0.75

public HashMap() {
   
    this.loadFactor = DEFAULT_LOAD_FACTOR;
}

创建一个指定初始容量的HashMap,默认负载因子为0.75

public HashMap(int initialCapacity) {
   
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

创建一个指定初始容量和负载因子的HashMap。

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;  //负载因子 0.75
    //创建一个2的幂次容量大小的数组(对指定的容量值,取最大的2次幂)
    this.threshold = tableSizeFor(initialCapacity);  
}

创建一个包含指定Map中所有映射关系的新HashMap

public HashMap(Map<? extends K, ? extends V> m) {
   
    this.loadFactor = DEFAULT_LOAD_FACTOR;  //负载因子 0.75
    putMapEntries(m, false);
 }

3. put()

HashMap中的put方法用于将一个键值对(key-value)映射添加到HashMap中。其中,key表示要存储的键,value表示要存储的值。该方法的返回值为新添加的值

public V put(K key, V value) {
   
    return putVal(hash(key), key, value, false, true);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖界的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值