HashMap底层原理分析(put、get方法)

1、HashMap底层原理分析(put、get方法)

HashMap底层是通过数组加链表的结构来实现的。HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那hash值就是相同的。当hash值相同时,就会出现hash冲突,HashMap通过链表来解决冲突。

原理图:

实例:

import java.util.HashMap;
import java.util.Map;
?
public class HashMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("fruit", "apple");
        System.out.println(map.get("fruit"));

1、put方法分析

//添加键值对方法
public V put(K key, V value) {
        //如果key为null,则hash值为0,将这个entry放在索引为0的地方,即table[0]
        if (key == null)
            return putForNullKey(value);
        //key不为null
        int hash = hash(key.hashCode());//计算key的hashCode的hash值
        int i = indexFor(hash, table.length);//返回hash值所在的索引位置
        //遍历table[i]处的Entry,若存在key相同并且hash值相同,则用新元素替换旧元素
        for (Entry<K,V> 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;
            }
        }
       //不存在key相同hash值相同的元素,修改标记+1,进行元素添加
        modCount++;
        addEntry(hash, key, value, i);//将包含特定key、value和hash值的entry添加到特定的桶中
        return null;
    }

    //添加key为null的元素
    private V putForNullKey(V value) {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(0, null, value, 0);
        return null;
    }
    /**
     * Adds a new entry with the specified key, value and hash code to
     * the specified bucket.  It is the responsibility of this
     * method to resize the table if appropriate.
     *
     * Subclass overrides this to alter the behavior of put method.
     */
    void addEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<>(hash, key, value, e);
        if (size++ >= threshold)
            resize(2 * table.length);
    }

2、get方法分析

/**
* 返回映射的key对应的value值,若map不包含该key,返回null
*/
public V get(Object key) {
        if (key == null)//获取key为null的value值
            return getForNullKey();
        int hash = hash(key.hashCode());//计算key的hashCode的hash值
        //遍历数组中对应hash值的Entry链表,若Entry元素的hash值与hashCode的hash值相等并且key与查找的key相等,则返回此Entry元素的value值
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

原文地址:https://www.cnblogs.com/stm32stm32/p/9035519.html

时间: 2024-08-08 20:25:04

HashMap底层原理分析(put、get方法)的相关文章

基础进阶(一)之HashMap实现原理分析

HashMap实现原理分析 1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N).链表的特点是:寻址困难,插入和删除容易. 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的

String类原理分析及部分方法

//String类原理分析及部分方法 //http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html //http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html //String类包含在java.lang包中,这个包在java的时候就自动import //String类是唯一一个不需要new关键词来创建对象的类. public class Test{ public

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希望对你有所帮助~ 目录 本篇文章主要包括以下内容: HashMap 的存储结构 常用变量说明,如加载因子等 HashMap 的四个构造函数 tableSizeFor()方法及作用 put()方法详解 hash()方法,以及避免哈希碰撞的原理 resize()扩容机制及原理 get()方法 为什么HashMap链表会

JMM和Volatile底层原理分析

JMM和volatile分析 1.JMM:Java Memory Model,java线程内存模型 JMM:它是一个抽象的概念,描述的是线程和内存间的通信,java线程内存模型和CPU缓存模型类似,它是标准化的,用于屏蔽硬件和操作系统对内存访问的差异性. 2.JMM和8大原子操作结合 3.volatile的应用及底层原理探究 volatile : 轻量级的synchronized,在多处理器的开发中保证了共享变量的"可见性".可见性的意思:当一个线程修改了某个共享变量时,其他使用到该共

hashmap底层原理

从大的方向上来说,hashmap底层其实是采用数组+链表+红黑树的形式. 在数据插入过程中,随着数据量的增大,hashmap里通过数组扩容,链表转红黑树形式来存储数据的. 那么,数组扩容是什么时候进行扩容的呢? 其实,数组扩容是根据数组阈值来判定是否扩容,hashmap设定初始数组的个数默认是16个,而阈值则通过初始数组个数X默认加载因子0.75, 超过该阈值时,则链表(单链表)则转化为红黑树. hashmap的put过程: 在put的时候,是先根据存入hashmap的key计算出其hash值的

AQS底层原理分析

J.U.C 简介 Java.util.concurrent 是在并发编程中比较常用的工具类,里面包含很多用来在并发场景中使用的组件.比如线程池.阻塞队列.计时器.同步器.并发集合等等.并发包的作者是大名鼎鼎的 Doug Lea.我们在接下来剖析一些经典的比较常用的组件的设计思想. Lock Lock 在 J.U.C 中是最核心的组件,前面我们讲 synchronized 的时候说过,锁最重要的特性就是解决并发安全问题.为什么要以 Lock 作为切入点呢?如果有看过 J.U.C 包中的所有组件,一

HashMap底层代码分析

public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; //this.loadFactor为加载因子,其值为默认的加载因子常量:DEFAULT_LOAD_FACTOR的值,即0.75 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); //阈值,当容量达到默认容量的75%时,自动扩容 table = new Entry[DEFAULT_INITIAL_CA

Java面试&amp; HashMap实现原理分析

1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端.  数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N).链表的特点是:寻址困难,插入和删除容易. 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表

HashMap实现原理分析

1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表 链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N).链表的特点是:寻址困难,插入和删除容易. 哈希表 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表.