Hashmap是一个存储key-value的映射表。

优点:

  • 索引数据快,查找一个数据对的时间复杂度是O(1)
  • 增加、删除一个数据的时间复杂度是O(1)
  • key不能重复,可以存储一个null值

存储:

  • 通过key的hashcode值存储在指定数组下标中
  • 用链表存储hashcode值一样,都是key不一样的数据,链表长度大于8时转换为红黑树(为了提高查询效率)

HashMap的内部结构

Hashmap封装了一个Node数组进行存储key-value的键值对,常用的get和put等都是对这个Node数组进行操作。

Node有四个属性:key、value、hash、next

  • hash:32位的整数,通过key的hashcode计算出来,hash&(数组长度-1) = 元素在数组的下标
  • next:指向Node节点的指针,不同的key计算出来的hash值可能是一样的,如果要存储的下标位置已经有值了,用链表将元素连起来

初始化HashMap:一开始HashMap内部是一个空的Node数组,插入数据后才会被创建

HashMap的常用操作

HashMap一开始的Node数组是空的,在第一次put元素后会默认创建一个长度为n = 16的数组

put一个key-value元素进入map中

计算key的hashcode值算出hash,得出index=hash&(长度-1),将元素存在数组[index]的位置。

有两种情况:

  • index这个位置已经有key了,比如当数组的长度是16时,33&(16-1) = 1. ,  1 & (16 - 1) = 1 ; key值不同,但是index一样。

    这里就用到了Node的next属性,让数组index下标所在的(最后一个)元素的next指向插入的元素,

  • 可以直接将元素存入数组中

通过key从map中get一个元素

计算key的hashcode值算出hash,得出index=hash&(长度-1)

有两种情况:

  • 如果数组[index]的值为null,就说明不存在这个元素
  • 不为null,还得比较key值,通过遍历链表(如果有的话),一个个比较key值,返回key相同的元素,或null

HashMap的优化操作

  • 数组长度n永远是2的幂:hash&(n-1)是元素在数组的下标,(2的幂-1)的二进制会是一连串的1,然后与hash值进行与运算

    • 与运算之后的结果永远不会超过数组的界限
    • 充分的利用了hash值二进制
  • 负载因子:hashmap设置了一个0.75的阈值,也就是数组中的元素数量大于数组长度的0.75时,进行数组扩容,扩展成原来的两倍
    • 当数组长度不够时,会出现很多的hash冲突,就是链表很长,检索效率慢,扩容后通过hash&(n-1)会让很长的链表散开
  • 链表转换成红黑树:链表长度大于8,但是数组元素数量没达到阈值,会选择将链表转换为红黑树,提高查询效率
    • 要求数组长度已经大于64,避免数组扩容和链表转红黑树的冲突
  • hash值的计算:hash值的前16位与key的hashcode一样,后16位由hashcode的前16位与后16位异或运算得到
    • 充分利用hashcode的值,增加随机性,减少hash冲突

Java集合:HashMap的更多相关文章

  1. Java 集合 HashMap & HashSet 拾遗

    Java 集合 HashMap & HashSet 拾遗 @author ixenos 摘要:HashMap内部结构分析 Java HashMap采用的是冲突链表方式 从上图容易看出,如果选择 ...

  2. Java集合---HashMap源码剖析

    一.HashMap概述二.HashMap的数据结构三.HashMap源码分析     1.关键属性     2.构造方法     3.存储数据     4.调整大小 5.数据读取           ...

  3. [转载] Java集合---HashMap源码剖析

    转载自http://www.cnblogs.com/ITtangtang/p/3948406.html 一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射 ...

  4. Java集合--HashMap分析

    HashMap在Java开发中有着非常重要的角色地位,每一个Java程序员都应该了解HashMap. 本文主要从源码角度来解析HashMap的设计思路,并且详细地阐述HashMap中的几个概念,并深入 ...

  5. 1.Java集合-HashMap实现原理及源码分析

    哈希表(Hash  Table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常 ...

  6. java集合HashMap、HashTable、HashSet详解

    一.Set和Map关系 Set代表集合元素无序,集合元素不可重复的集合,Map代表一种由多个key-value组成的集合,map集合是set集合的扩展只是名称不同,对应如下 二.HashMap的工作原 ...

  7. Java集合——HashMap,HashTable,ConcurrentHashMap区别

    Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...

  8. Java集合——HashMap、HashTable以及ConCurrentHashMap异同比较

    0. 前言 HashMap和HashTable的区别一种比较简单的回答是: (1)HashMap是非线程安全的,HashTable是线程安全的. (2)HashMap的键和值都允许有null存在,而H ...

  9. java集合-HashMap

    HashMap基于哈希表的 Map 接口的实现,以 key-value 的形式存在.在 HashMap 中,key-value 总是会当做一个整体来处理,系统会根据 hash 算法来来计算 key-v ...

  10. java集合-HashMap源码解析

    HashMap 键值对集合 实现原理: HashMap 是基于数组 + 链表实现的. 通过hash值计算 数组索引,将键值对存到该数组中. 如果多个元素hash值相同,通过链表关联,再头部插入新添加的 ...

随机推荐

  1. 在STM32F401上移植uC/OS的一个小问题 [原创]

    STM32F401xx是意法半导体新推出的Cortex-M4内核的MCU,相较于已经非常流行的STM32F407xx和STM32F427xx等相同内核的MCU而言,其特点是功耗仅为128uA/MHz, ...

  2. 授予mysql的其他用户数据库的使用权限

    场景:不同的开发人员有不同的数据库的权限:也可适用于外包公司不同的开发权限. root用户登录数据库,命令行执行下面语句即可. grant select,delete,update,create,dr ...

  3. MySQL-04-SQL简单介绍

    SQL介绍 SQL 结构化查询语言 5.7 以后符合SQL92严格模式 通过sql_mode参数来控制 常用SQL分类 DDL:数据定义语言 DCL:数据控制语言 DML:数据操作语言 DQL:数据的 ...

  4. NOIP 模拟 $28\; \rm 割海成路之日$

    题解 \(by\;zj\varphi\) 用两个集合分别表示 \(1\) 边联通块,\(1,2\) 边联通块 . \(\rm son_x\) 表示当前节点通过 \(3\) 类边能到的 \(2\) 联通 ...

  5. C#基础知识---Lambda表达式

    一.Lambda表达式简介 Lambda表达式可以理解为匿名函数,可以包含表达式和语句.它提供了一种便利的形式来创建委托. Lambda表达式使用这个运算符--- "=>", ...

  6. C# 简单的对称加密

    const string KEY_64 = "HuidTeac";//注意了,是8个字符 const string IV_64 = "HuidTeac"; pu ...

  7. 在C#中使用C++编写的类——用托管C++进行封装

    现在在Windows下的应用程序开发,VS.Net占据了绝大多数的份额.因此很多以前搞VC++开发的人都转向用更强大的VS.Net.在这种情况下,有很多开发人员就面临了如何在C#中使用C++开发好的类 ...

  8. SSM整合二

    总结 <!-- 批量删除 --> <delete id="deleteAll"> delete from tbl_emp where emp_id in & ...

  9. 【java虚拟机】分代垃圾回收策略的基础概念

    作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/6602166.html 一.为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一 ...

  10. go实现堆排序

    package main import "fmt" func main(){ arr:=[]int{4,8,2,1,6,9,3,5,7,8,1,4} dui(arr) fmt.Pr ...