HashMap的理解
Hashmap的实现原理
默认它是存放了16个链表头的数组,存储数据的时候key先生成hashcode,根据hashcode把数据存放到相应链表中,那么是如何确定存放到哪个链表中的呢?采用hashcode%len(len是数组长度)。注意这个模数据取余,余数相同的放在同一个桶中的思想用在很多地方。然后hashmap有个静态内部类entry,可以说是hashmap存储数据的基础bean,属性包括key、value、next等,多个entry组成一个链表,有个数组table[],其中存储各个链表的初始节点,这就是hashMap的实现原型,最开始这个数组的长度就是16。
Hashmap存数据
通过key得到hashcode,hashcode对数组table[]长度取余放到相应的链表中。注意,新的键值对将放在链表的头部,放入同一个桶中的新的entry的next将会指向之前的链表头部的entry。为什么不放到尾部呢?很简单,对于一个有长度的链表,当有一个新的entry到来的时候,放到链表的尾部是需要从头部一直找到尾部的,有消耗无收益。
HashMap取数据
取数据的时候是根据hashcode取模直接在table[]中找到相应的链表,然后遍历链表取到value。
一定要注意的
一致性:在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数。
我们知道Map的key在存取数据时候,key需要经历两个过程:1、hashcode取模找链表。2、遍历链表中的entry并与entry的key进行equal比较,来寻找目标value。那么hashcode和equal方法就起了非常重要的作用。
这里分两个情况来说:
1、key为基础数据类型或常用的对象(如String)。这时候值相同的key一定是相同的hashcode,并且equal进行比较的时候,比较的就是值,那么这种情况下HashMap正常使用。
2、key为对象。Object中的equal只是简单的判断是不是同一个实例,比较的是两个对象之间的内存地址是否相同;Object的hashcode方法为默认的内存地址。而很多时候我们使用Map要求的key是逻辑上相同即可而不是要求一定要同一个对象,这就意味着相同值的不同对象会有不同的内存地址。那么使用Map存取的时候,<A对象,value>存入Map,此时B对象和A对象逻辑相等,我们希望拿B对象也能取出value,但是B对象和A对象不是同一对象,于是在hashcode过程中,不同的hashcode值导致去不到目标链表,取值为null;即使假设hashcode值不同但是取模之后也到了目标链表中(几率小),进行key的equal比较时,由于是不同对象,B依然无法取到value,取值为null。所以key为对象的情况下,我们需要重写hashcode方法和equal方法,达成逻辑相同则hashcode相同、equal比较也相同。也应该明白,String也为对象,但是hashcode和equals方法官方已经帮我们重写过了,所以可以直接用,而使用其他对象作为key的时候,这个过程就需要我们自己来完成。
HashMap的理解的更多相关文章
- 关于hashmap的理解
首先分析第一个比较重要的方法 put 方法,源码如下 public V put(K key, V value) { if (key == null) return putForNullKey(valu ...
- 关于java集合类HashMap的理解
一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外,HashMap ...
- 对HashMap的理解(三):ConcurrentHashMap
HashMap不是线程安全的.在并发插入元素的时候,有可能出现环链表,让下一次读操作出现死循环.避免HashMap的线程安全问题有很多方法,比如改用HashTable或Collections.sync ...
- 【大厂面试08期】谈一谈你对HashMap的理解?
摘要 HashMap的原理也是大厂面试中经常会涉及的问题,同时也是工作中常用到的Java容器,本文主要通过对以下问题进行分析讲解,来帮助大家理解HashMap的原理. 1.HashMap添加一个键值对 ...
- hashMap 深入理解
1.java 的hashMap 是通过 链地址 法来解决 hash冲突的 2.初始时是一个empty table, 第一次添加数据时检查到时空数组就会 生成指定容量的数组,也就是 在第一次使用时才初始 ...
- HashMap简单理解
1. hashmap基于哈希表的map接口实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable ...
- (惊艳)hashmap的理解(映射)
第一: hashmap在内存中是长这样的,数组+链表的形式 // HashMap采用链表法解决冲突,每一个Entry本质上是一个单向链表 transient Entry[] table; 第二: p ...
- 对HashMap的理解(一):HashMap的实现
一.HashMap介绍 1. 定义HashMap实现了Map接口,继承AbstractMap类.其中Map接口定义了键映射到值的规则,而AbstractMap类提供 Map 接口的骨干实现,以最大限度 ...
- 对HashMap的理解(二):高并发下的HashMap
在分析hashmap高并发场景之前,我们要先搞清楚ReHash这个概念.ReHash是HashMap在扩容时的一个步骤.HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和 ...
- 对java中hashmap深入理解
1.HashMap的结构是怎样的? 二维结构,第一维是数组,第二维是链表 2.Get方法的流程是怎样的? 先调用Key的hashcode方法拿到对象的hash值,然后用hash值对第一维数组的长度进行 ...
随机推荐
- python文档翻译之使用python解释器
Python解释器通常安装在/usr/local/bin/python3.6,把/usr/local/bin目录设置到UNIX shell的搜索路径就可以使用下面的命令运行python: python ...
- 定时任务与feign超时的纠葛,该咋优化?
1 背景 业务定时器应用半夜经常会触发熔断异常的告警邮件 根据邮件提示的类找到归纳以下表格 编号 报错方法 接口所属应用 所属定时任务类 A VipTradeReportFeignService#ge ...
- 快速上手spring
一.初始程序 1.在父类pom导入所需要的jar包 2.编写一个实体类 3.创建一个beans.xml,创建一个bean即创建一个user对象,可在bean内配置property即设置属性值 4.用测 ...
- 使用spring mvc拦截器 会话失效处理
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import ...
- 关于button和submit的form提交以及 页面跳转问题
最近在做官网的注册登录form提交时遇到了这个问题,1.0时因为使用普通的模板并没有出现页面跳转失败问题 由于2.0时更换了注册模板,此时按钮样式是以下样式 而在css样式的模板里使用的是button ...
- 用Docker swarm快速部署Nebula Graph集群
用Docker swarm快速部署Nebula Graph集群 一.前言 本文介绍如何使用 Docker Swarm 来部署 Nebula Graph 集群. 二.nebula集群搭建 2.1 环境准 ...
- 在C++中使用libuv时对回调的处理 (2)
前情简介 在完成了第一版的<在C++中使用libuv时对回调的处理>之后,在对项目进行开发的时候,还是感觉有一些难受. 因为在实际操作的时候,需要构建一个结构体,并且需要对这个结构体的内存 ...
- Mysql中把varchar类型的字段转化为tinyint类型的字段
因为之前不知道tinyint类型的用法,所以将一些状态属性字段类型设置成了varchar类型,然后用"是"和"否"来判断状态 后来了解到了tinyint,就想试 ...
- html 网页美化--2
html网页美化: 鼠标点击特效:爱心.爆炸烟花(有些特效在Chrome中无法实现,推荐使用edge) 背景樱花花瓣 鼠标滑动彩带 此代码也可以用于博客园主页美化(需要申请JS权限):复制到博客侧边栏 ...
- 一种基于均值不等式的Listwise损失函数
一种基于均值不等式的Listwise损失函数 1 前言 1.1 Learning to Rank 简介 Learning to Rank (LTR) , 也被叫做排序学习, 是搜索中的重要技术, 其目 ...