深入探究HashMap.put方法实现细节

在Java中,HashMap是应用最广泛的数据结构之一,它提供了一种基于键值对(key-value)的存储方式,可以快速地存取、删除和检索数据。其中,put方法是HashMap中最主要的方法之一,本文将从多个方面深入探究HashMap.put方法实现细节。

一、put方法的使用

在Java中,使用put方法将数据放入HashMap中,具体使用方式如下:

HashMap map = new HashMap();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

以上代码将三个键值对放入了HashMap中,即{“A”:1, “B”:2, “C”:3}。通过这种方式,就可以在HashMap中快速地存储和查找数据了。

二、put方法的实现

HashMap的底层实现是基于数组和链表(或红黑树)的,存储数据的时候,HashMap首先根据key的hashCode值来计算其在数组中的位置,然后将该位置上的数组元素作为链表头,如果链表头还没有存储过key-value,那么直接放入,否则需要遍历链表,找到最后一个元素后将其next指向新存储的元素。

下面是HashMap中put方法的重要代码实现:

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

在上面的代码中,如果table数组还没有初始化,需要先进行初始化。然后,根据key的hashCode值和table数组的长度,计算其在数组中的位置。接着,遍历在该位置上的链表,如果找到了相同的key-value,则更新value值并返回旧值;如果没有找到,则将新的key-value插入到链表的末尾。

三、关于hash方法

在put方法的实现中,需要先调用hash方法计算key的hashCode值。下面是HashMap中hash方法的代码实现:

final int hash(Object k) {
    int h = hashSeed;
    if (0 != h && k instanceof String) {
        return sun.misc.Hashing.stringHash32((String) k);
    }
    h ^= k.hashCode();
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

在上面的代码中,先获取hashSeed的值,如果该值不为0且key是String类型,就调用sun.misc.Hashing.stringHash32方法来计算hashCode值;否则,直接使用key的hashCode值。

为什么要进行h ^= (h >>> 20) ^ (h >>> 12)和h ^= (h >>> 7) ^ (h >>> 4)操作呢?这是为了使hashCode更加分散,从而减少哈希冲突的概率。上述操作使用了位运算,可以大幅提高计算效率。

四、关于扩容

当HashMap中元素数量达到了threshold(容量*负载因子)时,就会自动进行扩容操作。扩容实际上就是创建一个更大的table数组,然后将原来的元素重新分配到新数组中。下面是HashMap中resize方法的代码实现:

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }
    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable, initHashSeedAsNeeded(newCapacity));
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}

在代码中,首先获取原table数组的长度,然后判断是否达到了最大容量(2的30次方)。如果已达到最大容量,则不再进行扩容。否则,创建一个新的Entry数组,调用transfer方法将原table数组中的元素重新分配到新数组中。最后将table指向新数组,同时更新threshold的值。

五、关于线程安全

HashMap并不是线程安全的,即如果多个线程同时对同一个HashMap进行操作,可能会出现不一致的结果。因此,在并发环境下应该使用ConcurrentHashMap来替代HashMap,后者是线程安全的。

六、小结

通过以上分析,我们深入探究了HashMap.put方法的实现细节。在使用HashMap的过程中,尤其要注意hash方法和扩容的相关实现,同时要在并发场景下使用线程安全的ConcurrentHashMap。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/242169.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 12:47
下一篇 2024-12-12 12:47

相关推荐

  • int类型变量的细节与注意事项

    本文将从 int 类型变量的定义、声明、初始化、范围、运算和类型转换等方面,对 int 类型变量进行详细阐述和讲解,帮助读者更好地掌握和应用 int 变量。 一、定义与声明 int…

    编程 2025-04-29
  • 解决.net 6.0运行闪退的方法

    如果你正在使用.net 6.0开发应用程序,可能会遇到程序闪退的情况。这篇文章将从多个方面为你解决这个问题。 一、代码问题 代码问题是导致.net 6.0程序闪退的主要原因之一。首…

    编程 2025-04-29
  • ArcGIS更改标注位置为中心的方法

    本篇文章将从多个方面详细阐述如何在ArcGIS中更改标注位置为中心。让我们一步步来看。 一、禁止标注智能调整 在ArcMap中设置标注智能调整可以自动将标注位置调整到最佳显示位置。…

    编程 2025-04-29
  • Python中init方法的作用及使用方法

    Python中的init方法是一个类的构造函数,在创建对象时被调用。在本篇文章中,我们将从多个方面详细讨论init方法的作用,使用方法以及注意点。 一、定义init方法 在Pyth…

    编程 2025-04-29
  • Python创建分配内存的方法

    在python中,我们常常需要创建并分配内存来存储数据。不同的类型和数据结构可能需要不同的方法来分配内存。本文将从多个方面介绍Python创建分配内存的方法,包括列表、元组、字典、…

    编程 2025-04-29
  • 用不同的方法求素数

    素数是指只能被1和自身整除的正整数,如2、3、5、7、11、13等。素数在密码学、计算机科学、数学、物理等领域都有着广泛的应用。本文将介绍几种常见的求素数的方法,包括暴力枚举法、埃…

    编程 2025-04-29
  • Python中读入csv文件数据的方法用法介绍

    csv是一种常见的数据格式,通常用于存储小型数据集。Python作为一种广泛流行的编程语言,内置了许多操作csv文件的库。本文将从多个方面详细介绍Python读入csv文件的方法。…

    编程 2025-04-29
  • 使用Vue实现前端AES加密并输出为十六进制的方法

    在前端开发中,数据传输的安全性问题十分重要,其中一种保护数据安全的方式是加密。本文将会介绍如何使用Vue框架实现前端AES加密并将加密结果输出为十六进制。 一、AES加密介绍 AE…

    编程 2025-04-29
  • Python学习笔记:去除字符串最后一个字符的方法

    本文将从多个方面详细阐述如何通过Python去除字符串最后一个字符,包括使用切片、pop()、删除、替换等方法来实现。 一、字符串切片 在Python中,可以通过字符串切片的方式来…

    编程 2025-04-29
  • 用法介绍Python集合update方法

    Python集合(set)update()方法是Python的一种集合操作方法,用于将多个集合合并为一个集合。本篇文章将从以下几个方面进行详细阐述: 一、参数的含义和用法 Pyth…

    编程 2025-04-29

发表回复

登录后才能评论