文章目录4、put方法详解5、get方法6、hash()计算原理7、()扩容机制8、常见的一些面试问题
1、结构
JDK7与JDK8及以后的结构与存储原理有所不同:
Jdk1.7:数组 + 链表 ( 当数组下标相同,则会在该下标下使用链表)
Jdk1.8:数组 + 链表 + 红黑树 (预值为8 如果链表长度 >=8则会把链表变成红黑树 )
Jdk1.7中链表新元素添加到链表的头结点,先加到链表的头节点,再移到数组下标位置
Jdk1.8中链表新元素添加到链表的尾结点
【2、HashMap中的常量】(数组通过下标索引查询,所以查询效率非常高,链表只能挨个遍历,效率非常低 。jdk1.8及以
上版本引入了红黑树,当链表的长度大于或等于8的时候则会把链表变成红黑树,以提高查询效率)
中的数组通常被称为桶数组
如下图所示:
文章插图
数组存放了一个key-value实例,在jdk7中叫Entry在jdk8中叫Node,红黑树中的结点是
Node继承与Map.Entry,继承于Node
2、中的常量
//默认的初始化容量为16,必须是2的n次幂static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16//最大容量为 2^30static final int MAXIMUM_CAPACITY = 1 << 30;//默认的加载因子0.75,乘以数组容量得到的值,用来表示元素个数达到多少时,需要扩容 。//为什么设置 0.75 这个值呢,简单来说就是时间和空间的权衡 。//若小于0.75如0.5,则数组长度达到一半大小就需要扩容,空间使用率大大降低,//若大于0.75如0.8,则会增大hash冲突的概率,影响查询效率 。static final float DEFAULT_LOAD_FACTOR = 0.75f;//刚才提到了当链表长度过长时,会有一个阈值,超过这个阈值8就会转化为红黑树static final int TREEIFY_THRESHOLD = 8;//当红黑树上的元素个数,减少到6个时,就退化为链表static final int UNTREEIFY_THRESHOLD = 6;//链表转化为红黑树,除了有阈值的限制,还有另外一个限制,需要数组容量至少达到64,才会树化 。//这是为了避免,数组扩容和树化阈值之间的冲突 。static final int MIN_TREEIFY_CAPACITY = 64;//存放所有Node节点的数组transient Node[] table;//存放所有的键值对transient Set> entrySet;//map中的实际键值对个数,即数组中元素个数transient int size;//每次结构改变时,都会自增,fail-fast机制,这是一种错误检测机制 。//当迭代集合的时候,如果结构发生改变,则会发生 fail-fast,抛出异常 。transient int modCount;//数组扩容阈值int threshold;//加载因子final float loadFactor;//普通单向链表节点类static class Node implements Map.Entry {//key的hash值,put和get的时候都需要用到它来确定元素在数组中的位置final int hash;final K key;V value;//指向单链表的下一个节点Node next;Node(int hash, K key, V value, Node next) {this.hash = hash;this.key = key;this.value = http://www.kingceram.com/post/value;this.next = next;}}//转化为红黑树的节点类static final class TreeNode extends LinkedHashMap.Entry {//当前节点的父节点TreeNode parent;//左孩子节点TreeNode left;//右孩子节点TreeNode right;//指向前一个节点TreeNode prev;// needed to unlink next upon deletion//当前节点是红色或者黑色的标识boolean red;TreeNode(int hash, K key, V val, Node next) {super(hash, key, val, next);}}
这里就引申而来几个问题:
问题一:为什么的默认负载因子是0.75,而不是0.5或者是整数1呢?
阈值() = 负载因子() x 容量() 根据的扩容机制,他会保证容量()的值永远都是2的幂 为了保证负载因子x容量的结果是一个整数,这个值是0.75(4/3)比较合理,因为这个数和任何2的次幂乘积结果都是整数 。理论上来讲,负载因子越大,导致哈希冲突的概率也就越大,负载因子越小,费的空间也就越大,这是一个无法避免的利弊关系,所以通过一个简单的数学推理,可以测算出这个数值在0.75左右是比较合理的
- window10,JDK、Jre安装及环境配置
- 数组+链表+红黑树 HashMap底层数据结构
- python
- 测试工程师笔试题整理01
- 人工智能算法几个重要指标
- 人工智能算法整理
- 2、匿名函数定义和调用的三种方式
- centos7 搭建 tinyProxy代理
- 一 HTML:开发工具
- NR中的同步信号SS(包含PSS,主同步信号和辅同步信号,S