HashMap基本介绍
1.HashMap简介(本文是按照JDK1.8进行解析)
HashMap位于JDK自带jar包rt.jar的java.util目录下。 HashMap是一个散列表,存储的内容是键值对<key,value>映射。
HashMap继承于AbstractMap,实现了Map、Cloneable、Serializable接口 HashMap是线程不安全的,其中key、value都可以为null,且是无序的。
2.HashMap的数据结构
通常的数据结构有数组和链表两种,他们各有优缺点。
数组:如下图示:

数组的存储区间是连续的,即使对应位置值为空也需要分配内存,所以占用内存较多,但是数组查找数据很容易,只需要知道对应的下标值即可,二分查找时间复杂度为O(1);
但是数组新增和删除元素比较复杂,比如现在需要删除下标为3的Arr4,下标为3后面的元素全部需要左移一位,在下标为3后面插入一条数据同理,后面的数据全部需要右移。
总结
数组的优点是:查找容易
数组的缺点是:新增和删除复杂、占用内存严重
链表:如下图示:

链表的存储区间很离散,占用内存的数据都是有效数据,占用内存较少,插入数据容易,比如在节点2和节点3之间插入一条数据,只需将节点2的next指向新节点,新节点的next指向节点3即可;
删除节点3,则值需将节点2的next指向节点4即可,都不影响其他的节点,但是如果需要查询一个节点比较困难,需要从节点1开始遍历每个节点,才可以找到需要查询的节点位置。
总结
链表的优点是:新增和删除容易、占用内存较少
链表的缺点是:查询比较复杂
而HashMap是综合了数组和链表的特性,实现了即查询容易,插入和删除也容易的数据结构;如下图示:

可见HashMap的数据结构其实还是数组,只是数组里存储的数据是一个链表。
那么HashMap是怎么做到的呢?
首先HashMap需要有一个链表的线性数组,Node<K,V>[] table
Node是HashMap的内部类,存储在数组指定位置的节点,主要属性有hash、key、value和next
接下来再分析下HashMap是怎么工作的?
1.HashMap初始化
HashMap主要有四个构造方法,主要是初始化HashMap的loadFactor(加载因子)和threshold (扩容长度)
loadFactor是HashMap的加载因子,默认是0.75,HashMap默认长度是16,当HashMap中存入的数据长度达到总长度size*loadFactor的时候就需要开始扩容,
也就是说当HashMap使用到12的时候就需要开始扩容,默认是对数组进行2倍的扩容,扩容后的总长度就是threshold。
2.put的流程
当HashMap存入数据调用put方法,先根据传入的key值,取对应的哈希码,获取到一个int类型的hash值,这个hash值对应的数字就是该数据需要存入到数组对应的下标位置,
如存入一个key通过计算得到hash值为2,则该数据就存入table[2]中。这里会有两种情况,一种是插入之前table[2]的位置还没有存入数据,则直接将数据存入table[2]的位置,当是如果
此时table[2]的位置已经存有数据,则通过链表的形式,将数据插入到table[2]的链表尾,如下图示:

当key获取到的hash值对应的位置已经存在数据的时候,不是立马将数据存入到对应链表的尾部,而是先判断这个key是否已经存在table中,比如现在再重新put一遍<"赵五","30岁">,通过key的hash值知道需要放在table[1]的位置,那么会从链表头开始挨个判断key值是否等于当前的key值,如果两个key和hash值都相等,则不会加入到链表尾,而是直接更新value值
3.get的流程
现在由于知道了HashMap是如何存入数据的,现在从HashMap取数据就相对比较容易理解了,先是通过key取对应的hash值,就可以很容易定位到数据是存在table的那个位置,如果对应的位置链表长度只有1,且key相等,则取出value;如果链表长度不为1,则遍历链表,挨个判断key是否等于需要查找的key,找到了便返回对应的value
4.扩容resize的流程
当HashMap一直put操作,HashMap容量是有限的,就需要进行扩容,HashMap会有一个阈值,就是当前数组的长度 * 加载因子(默认是0.75)
由于数组是无法自动扩容的,所以需要创建新的数组来替换旧的数组。如果不进行扩容,还是默认的长度16的话,如果插入160条数据的话,那么数组每一个位置的链表长度平均都为10,会影响查询的效率;
hashMap扩容的时候默认是对当前数组进行2倍扩容,也就是默认是长度为16,则扩容一次后长度为32,扩容两次就是64。
另外扩容之后原先的table中的数据位置可能会进行改变,因为通过hash值获取到的位置可能已经不再是原来的位置了,每个元素都需要重新计算新的位置,所以resize方法是比较消耗性能的。

关于HashMap的具体实现
tips:
1.HashMap的长度和HashMap中的数组长度是两个概念,比如新建一个HashMap,put一条数据,此时数组的长度是默认的16,而HashMap的size则为1.
如果put进10条数据,且10条数据的hash值都一样,则会存入数组的同一个链表下,此时数组只有一个位置存有数据,但是HashMap的size则为10
HashMap基本介绍的更多相关文章
- Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
概要 这一章,我们对HashMap进行学习.我们先对HashMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashMap.内容包括:第1部分 HashMap介绍第2部分 HashMa ...
- Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- JAVA HashMap详细介绍和示例
http://www.jb51.net/article/42769.htm 我们先对HashMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashMap. 第1部分 HashMa ...
- 【转】Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
概要 这一章,我们对HashMap进行学习.我们先对HashMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashMap.内容包括:第1部分 HashMap介绍第2部分 HashMa ...
- HashMap简单介绍
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表. 一.什么是哈希表 在讨论哈希表之 ...
- HashMap方法介绍
1. Map的遍历方式 (1) for each map.entrySet() Map<String, String> map = new HashMap<String, Strin ...
- Java HashMap详细介绍和使用示例
①对HashMap的整体认识 HashMap是一个散列表,它存储的内容是键值对(key-value)映射. HashMap继承于AbstractMap,实现了Map.Cloneable.java.io ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
概要 前一章,我们学习了HashMap.这一章,我们对Hashtable进行学习.我们先对Hashtable有个整体认识,然后再学习它的源码,最后再通过实例来学会使用Hashtable.第1部分 Ha ...
随机推荐
- Memo-Tech
Qt install Qt on Ubuntu Download *.run file; Click downloaded file to install. Note that gcc module ...
- Everything 本地磁盘文件搜索工具下载!
如何运用布尔算子? AND(且)是缺省使用的布尔算子. 例如:如果要搜索 foo 和 bar 同时出现的文件:foo bar 如果从两者之中任一个都可以,则用 | 介于两者之间. 例如:如果要搜索.j ...
- 开始导入第一个第三方库jieba
在做python的练习题,想看看运行结果. 谁知,有道题,不能识别jieba,原来要导入,因为是第三方库,照着书里面的导入方法,有三种,一种是用pip,在命令行里面安装,使用pip - p 可以查看p ...
- 数学--数论--HDU 1792 A New Change Problem (GCD+打表找规律)
Problem Description Now given two kinds of coins A and B,which satisfy that GCD(A,B)=1.Here you can ...
- CodeForces - 1047CEnlarge GCD(这题很难,快来看题解,超级详细,骗浏览量)
C. Enlarge GCD time limit per test1 second memory limit per test256 megabytes inputstandard input ou ...
- spring源码阅读笔记10:bean生命周期
前面的文章主要集中在分析Spring IOC容器部分的原理,这部分的核心逻辑是和bean创建及管理相关,对于单例bean的管理,从创建好到缓存起来再到销毁,其是有一个完整的生命周期,并且Spring也 ...
- V - Can you answer these queries? HDU - 4027 线段树 暴力
V - Can you answer these queries? HDU - 4027 这个题目开始没什么思路,因为不知道要怎么去区间更新这个开根号. 然后稍微看了一下题解,因为每一个数开根号最多开 ...
- 工具类CountDownLatch的应用---百米赛跑案例
package com.aj.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Execu ...
- leetcode_二叉树验证(BFS、哈希集合)
题目描述: 二叉树上有 n 个节点,按从 0 到 n - 1 编号,其中节点 i 的两个子节点分别是 leftChild[i] 和 rightChild[i]. 只有 所有 节点能够形成且 只 形成 ...
- 【Linux基础总结】Shell 基础编程
Shell 基础编程 重启虚拟机遇到磁盘损坏如何解决 Shell编程中变量的声明.引用及作用域 Shell程序 概述 以文件形式存放批量的Linux命令集合,该文件能够被Shell解释执行,这种文件就 ...