一、HashMap
1、基于哈希表的 Map 接口的实现。
此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
2、HashMap 的实例有两个参数影响其性能:初始容量 和 加载因子。
容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。
加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
按照key关键字的哈希值和buckets数组的长度取模查找桶的位置,如果key的哈希值相同,Hash冲突(也就是指向了同一个桶)则每次新添加的作为头节点,而最先添加的在表尾。
HashMap中的桶的个数就是下图中的0- n的数组的长度,存储第一个entry的位置叫桶(bucket)而桶中只能存一个值也就是链表的头节点,链表的每个节点就是添加的一个值(HashMap内部类Entry的实例Entry有哪些属性之后在详说)。
也可以这样理解,一个entry 类型的存储链表的数组。数组的索引位置就是一个个桶的索引地址。
从上图我们可以发现哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。
一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12、28%16=12、108%16=12、140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。
HashMap简单总结:
1、HashMap 是链式数组(存储链表的数组)实现查询速度可以,而且能快速的获取key对应的value;
2、查询速度的影响因素有 容量和负载因子,容量大负载因子小查询速度快但浪费空间,反之则相反;
3、数组的index值是(key 关键字, hashcode为key的哈希值, len 数组的大小):hashcode%len的值来确定,如果容量大负载因子小则index相同(index相同也就是指向了同一个桶)的概率小,链表长度小则查询速度快,反之index相同的概率大链表比较长查询速度慢。
4、对于HashMap以及其子类来说,他们是采用hash算法来决定集合中元素的存储位置,当初始化HashMap的时候系统会创建一个长度为capacity的Entry数组,这个数组里可以存储元素的位置称为桶(bucket),每一个桶都有其指定索引,系统可以根据索引快速访问该桶中存储的元素。
5、无论何时HashMap 中的每个桶都只存储一个元素(Entry 对象)。由于Entry对象可以包含一个引用变量用于指向下一个Entry,因此可能出现HashMap 的桶(bucket)中只有一个Entry,但这个Entry指向另一个Entry 这样就形成了一个Entry 链。
6、通过上面的源码发现HashMap在底层将key_value对当成一个整体进行处理(Entry 对象)这个整体就是一个Entry对象,当系统决定存储HashMap中的key_value对时,完全没有考虑Entry中的value,而仅仅是根据key的hash值来决定每个Entry的存储位置。
注意点
JDK1.8中使用一个Node数组来存储数据,但这个Node可能是链表结构,也可能是红黑树结构如果插入的key的hashcode相同,那么这些key也会被定位到Node数组的同一个格子里。
如果同一个格子里的key不超过8个,使用链表结构存储。如果超过了8个,那么会调用treeifyBin函数,将链表转换为红黑树。那么即使hashcode完全相同,由于红黑树的特点,查找某个特定元素,也只需要O(log n)的开销。
也就是说put/get的操作的时间复杂度最差只有O(log n)。
需要注意:key的对象,必须正确的实现了Compare接口
二、TreeMap
1、红黑树是一种近似平衡的二叉查找树,它能够确保任何一个节点的左右子树的高度差不会超过二者中较低那个的一倍。具体来说,红黑树是满足如下条件的二叉查找树(binary search tree):
  1. 每个节点要么是红色,要么是黑色。
  2. 根节点必须是黑色
  3. 红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色)。
  4. 对于每个节点,从该点至null(树尾端)的任何路径,都含有相同个数的黑色节点。
在树的结构发生改变时(插入或者删除操作),往往会破坏上述条件3或条件4,需要通过调整使得查找树重新满足红黑树的条件。
2、TreeMap的底层使用了红黑树来实现,像TreeMap对象中放入一个key-value 键值对时,就会生成一个Entry对象,这个对象就是红黑树的一个节点,其实这个和HashMap是一样的,一个Entry对象作为一个节点,只是这些节点存放的方式不同。
3、存放每一个Entry对象时都会按照key键的大小按照二叉树的规范进行存放,所以TreeMap中的数据是按照key从小到大排序的。
TreeMap总结:
程序添加新节点时,总是从树的根节点开始比较,即将根节点当成当前节点。如果新增节点大于当前节点并且当前节点的右节点存在,则以右节点作为当前节点,如果新增节点小于当前节点并且当前节点的左子节点存在,则以左子节点作为当前节点;
如果新增节点等于当前节点,则用新增节点覆盖当前节点,并结束循环 直到某个节点的左右子节点不存在,将新节点添加为该节点的子节点。如果新节点比该节点大,则添加其为右子节点。如果新节点比该节点小,则添加其为左子节点。
最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!

一篇文章搞清楚HashMap和TreeMap的内部结构的更多相关文章

  1. 一篇文章搞定百度OCR图片文字识别API

    一篇文章搞定百度OCR图片文字识别API https://www.jianshu.com/p/7905d3b12104

  2. 一篇文章搞懂高级程序员、架构师、技术总监、CTO从薪资到技能的区别

    一篇文章搞懂高级程序员.架构师.技术总监.CTO从薪资到技能的区别 http://youzhixueyuan.com/senior-programmers-architects-technical-d ...

  3. 一篇文章搞定Git——Git代码管理及使用规范

    一篇文章搞定Git--Git代码管理及使用规范   https://blog.csdn.net/weixin_42092278/article/details/90448721

  4. 一篇文章搞懂python2、3编码

    说在前边: 编码问题一直困扰着每一个程序员的编程之路,如果不将它彻底搞清楚,那么你的的这条路一定会走的格外艰辛,尤其是针对使用python的程序员来说,这一问题更加显著, 因为python有两个版本, ...

  5. 一篇文章搞明白CORS跨域

    面试问到数据交互的时候,经常会问跨域如何处理.大部分人都会回答JSONP,然后面试官紧接着就会问:"JSONP缺点是什么啊?"这个时候坑就来了,如果面试者说它支持GET方式,然后面 ...

  6. 一篇文章搞定JS类型转换

    啥要说这个东西?一道面试题就给我去说它的动机.题如下: var bool = new Boolean(false); if (bool) { alert('true'); } else { alert ...

  7. 五分钟学Java:一篇文章搞懂spring和springMVC

    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在什么时候?相信很多人和我一样,第一次了 ...

  8. 一篇文章搞懂filebeat(ELK)

    本文使用的filebeat是7.7.0的版本本文从如下几个方面说明: filebeat是什么,可以用来干嘛 filebeat的原理是怎样的,怎么构成的 filebeat应该怎么玩 一.filebeat ...

  9. 一篇文章搞定 Nginx 反向代理与负载均衡

    代理 要想弄明白反向代理,首先要知道啥是正向代理,要搞懂正向代理只需要知道啥是代理即可.代理其实就是一个中介,在不同事物或同一事物内部起到居间联系作用的环节.比如买票黄牛,房屋中介等等. 在互联网中代 ...

随机推荐

  1. Andorid开发中遇到的问题

    最近开始学习开发Android App,找了本教程,学了一些基本知识后,就开始着手做一个例子. 我始终觉得在做中学,可能会稍微快一点.很快,一个具有初步功能的App被我撸出来了. 在模拟器上运行,我发 ...

  2. HBase 基本入门

    目录 一.简介 有什么特性 与RDBMS的区别 二.数据模型 三.安装HBase 四.基本使用 表操作 五.FAQ 参考文档 无论是 NoSQL,还是大数据领域,HBase 都是非常"炙热& ...

  3. vue 安装指令

    vue init webpack 项目名 创建项目cd 项目名 打开项目 npm install vuex --save 安装vuex在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来 ...

  4. Relation-Shape Convolutional Neural Network for Point Cloud Analysis(CVPR 2019)

    代码:https://github.com/Yochengliu/Relation-Shape-CNN 文章:https://arxiv.org/abs/1904.07601 作者直播:https:/ ...

  5. nginx一:安装和基本应用

    Nginx: 目录 Nginx:... 1 NGINX简介和安装... 1 网站... 1 全称... 2 二次开发版... 2 Nginx的特性... 2 基本功能... 2 web服务相关的功能. ...

  6. 小程序如何判断用户(后台使用Django)

    小程序如何判断用户是哪个: 有Web开发经验的都知道,客户端用户发起请求,服务器收到请求后,可以通过把用户user_id记录到session里,然后下次通过session里面的user_id来辨别是哪 ...

  7. springboot2中使用dubbo的三重境界

    在springboot中使用dubbo,本来是件挺简单的事情,但现实的世界就是如此的复杂,今天我用一个亲身经历的跳坑和填坑的事来讲在spring boot中使用高版本dubbo(当当的魔改版)的三重境 ...

  8. 启动项目报错:org.apache.catalina.LifecycleException: Failed to start component

    原因 环境异常重启,项目java进程未关闭,原项目的端口依旧在占用. 一般为8080端口被占用 解决方法 以下两种方法都可以解决,原理相同(结束异常进程) 1. 简单粗暴: 打开任务管理器找到java ...

  9. 源码分析 RocketMQ DLedger 多副本之 Leader 选主

    目录 1.DLedger关于选主的核心类图 1.1 DLedgerConfig 1.2 MemberState 1.3 raft协议相关 1.4 DLedgerRpcService 1.5 DLedg ...

  10. 以面向对象的思维,搭建Android与多ble蓝牙设备并发通讯小框架

    Android连接多蓝牙设备.蓝牙与多设备连接.蓝牙ble多设备并发操作.Android连接不了.Android ble开发框架.Android 连接蓝牙总结 前言 小白请绕道百度,本文适合有一定An ...