从leetCode的手动实现HashMap说起

427 阅读2分钟

HashMap

LeetCode No.706

某日笔者完成了LeeCode No.706 设计哈希映射的题,题干就是手动实现一个基于<Integer,Integer>的get、put、remove以及初始化内容。在完成了题目之后,又燃起了我对于JDK中HashMap实现的研究热情,遂努力地去研究了一番代码,为了更好的记忆这些要点,我会一点一点地将Java中HashMap的实现要点写在这篇文章中。同时,以下文章中关于HashMap的代码内容将主要以JDK1.8的代码作为参考。

介绍

HashMap中文名又叫哈希表,散列表,是一种O(1)时间复杂度来存储以及读取一类<K,V>结构数据的表单数据结构。

基本原理

这里我给出自己对于HashMap的理解,关键在于使用映射的方式将元素散列至表中,哈希表中的保存与提取方法都利用了键映射寻址的方式来用公式记忆了存放的地址。这个公式多种多样,诸如最常见的取模、数字分析、线性函数法等。 HashMap(JDK1.8)的几大主要操作有:

  • 存放数据(键值对):put(key,value);
  • 获取数据:get(key)然后返回之前存放的value;
  • 初始化Map:java中使用了Node数组tab来实现,默认数组大小为16,同时设置扩容的阈值,默认阈值为0.75(即75%);
  • 扩容Node数组:当保存的键值对数量达到一定阈值之后,HashMap会执行扩容操作,Java中执行两倍扩容;

数据结构

存放与获取(Put and Get)

在java的HashMap中,采用了最常见的取模的方式来获得当前key的位置,在put方法中,我们可以找到这样的一段代码:

(n-1)&hash

节点结构与数组(Nodes)

初始化(Initialization)

阈值与扩容(Factor and Resize)

JDK1.8相对于1.7的改动