HashMap和TreeMap的内部结构

1、HashMap 

一、基于哈希表的 Map 接口的实现。此实现提供全部可选的映射操做,并容许使用 null 值和 null 键。(除了非同步和容许使用 null 以外,HashMap 类与 Hashtable 大体相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
二、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。因此十二、2八、108以及140都存储在数组下标为12的位置。
 

HashMap简单总结:

一、HashMap 是链式数组(存储链表的数组)实现查询速度能够,并且能快速的获取key对应的value;
二、查询速度的影响因素有 容量和负载因子,容量大负载因子小查询速度快但浪费空间,反之则相反;
三、数组的index值是(key 关键字, hashcode为key的哈希值, len 数组的大小):hashcode%len的值来肯定,若是容量大负载因子小则index相同(index相同也就是指向了同一个桶)的几率小,链表长度小则查询速度快,反之index相同的几率大链表比较长查询速度慢。
四、对于HashMap以及其子类来讲,他们是采用hash算法来决定集合中元素的存储位置,当初始化HashMap的时候系统会建立一个长度为capacity的Entry数组,这个数组里能够存储元素的位置称为桶(bucket),每个桶都有其指定索引,系统能够根据索引快速访问该桶中存储的元素。
五、不管什么时候HashMap 中的每一个桶都只存储一个元素(Entry 对象)。因为Entry对象能够包含一个引用变量用于指向下一个Entry,所以可能出现HashMap 的桶(bucket)中只有一个Entry,但这个Entry指向另外一个Entry 这样就造成了一个Entry 链。
六、经过上面的源码发现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接口函数

2、TreeMap

红黑树是一种近似平衡的二叉查找树,它可以确保任何一个节点的左右子树的高度差不会超过两者中较低那个的一陪。具体来讲,红黑树是知足以下条件的二叉查找树(binary search tree):性能

  1. 每一个节点要么是红色,要么是黑色。code

  2. 根节点必须是黑色对象

  3. 红色节点不能连续(也便是,红色节点的孩子和父亲都不能是红色)。blog

  4. 对于每一个节点,从该点至null(树尾端)的任何路径,都含有相同个数的黑色节点。排序

在树的结构发生改变时(插入或者删除操做),每每会破坏上述条件3或条件4,须要经过调整使得查找树从新知足红黑树的条件。索引

 

 

 
二、TreeMap的底层使用了红黑树来实现,像TreeMap对象中放入一个key-value 键值对时,就会生成一个Entry对象,这个对象就是红黑树的一个节点,其实这个和HashMap是同样的,一个Entry对象做为一个节点,只是这些节点存放的方式不一样。
三、存放每个Entry对象时都会按照key键的大小按照二叉树的规范进行存放,因此TreeMap中的数据是按照key从小到大排序的。
 
TreeMap总结:
   程序添加新节点时,老是从树的根节点开始比较,即将根节点当成当前节点。若是新增节点大于当前节点而且当前节点的右节点存在,则以右节点做为当前节点,若是新增节点小于当前节点而且当前节点的左子节点存在,则以左子节点做为当前节点;若是新增节点等于当前节点,则用新增节点覆盖当前节点,并结束循环 直到某个节点的左右子节点不存在,将新节点添加为该节点的子节点。若是新节点比该节点大,则添加其为右子节点。若是新节点比该节点小,则添加其为左子节点;
相关文章
相关标签/搜索