一、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. 自制反汇编工具使用实例 其二(使用xmm寄存器初始化对象,以及空的成员函数指针)

    在反汇编代码中,当看到xmm寄存器,第一反应是将要进行浮点操作或访问,但是更加多的情况是在使用xmm寄存器初始化局部对象. 下面是自制反汇编工具翻译出来的代码: // -[CALayer setAll ...

  2. [Part 1] Ubuntu 16.04安装和配置QT5 | Part-1: Install and Configure Qt5 on Ubuntu 16.04

    本文首发于个人博客https://kezunlin.me/post/91842b71/,欢迎阅读! Part-1: Install and Configure Qt5 on Ubuntu 16.04 ...

  3. Mysql 存储过程声明及使用

    存储过程(Stored Procedure):是一组用于完成特定数据库功能的sql语句集,该sql语句集经过编译后存储在数据库系统中,在使用的时候,用户通过调用指定已经定义好的存储过程并执行它,从而完 ...

  4. 洛谷P2634 聪聪可可 (点分治)

    ###题目链接### 题目大意: 给你一棵树,假如树上两点间的距离是 3 的倍数 的点对有 s 对,则输出最简分数  s/n ,其中 n 表示所有整棵树的点对总数. 分析: 1.显然,可以采用点分治. ...

  5. nmap中的详细命令

    nmap全部参数详解-A 综合性扫描端口:80http 443https 53dns 25smtp 22ssh 23telnet20.21ftp 110pop3 119nntp 143imap 179 ...

  6. SpringMVC配置了拦截器(interceptors)却显示不出css、js样式的解决办法

    首先因为在web.xml里面配置了 <filter-mapping> <filter-name>characterEncodingFilter</filter-name& ...

  7. Find命令、文件名后缀、Linux和Windows互传文件 使用介绍

    第2周第5次课(3月30日) 课程内容: 2.23/2.24/2.25 find命令2.26 文件名后缀 2.27 Linux和Windows互传文件 find命令 文件查找: 1.which(一般用 ...

  8. windows下安装python numpy+scipy+matlotlib+scikit-learn等流行库

    (1)请不要直接使用   pip install scikit-learn pip install Numpy pip install Scipy pip install Matplotlib 命令安 ...

  9. SpringBoot+Mybatis 实现动态数据源切换方案

    背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文 ...

  10. 【Python成长之路】从零学GUI -- 制作智能聊天机器人

    [写在前面] 鹏哥:最近老惹小燕同学不开心,结果都没人陪我聊天了.哎,好无聊呀! 肥宅男:女朋友什么的最无聊了,还没我的图灵机器人好玩. 鹏哥:图灵?好巧,和我部门同名. [效果如下] [实现过程] ...