美团面试题:Hashmap的结构,1.7和1.8有哪些区别,深入的分析

(一) 真实面试题之:Hashmap的结构,1.7和1.8有哪些区别

不同点:
(1)JDK1.7用的是头插法,而JDK1.8及之后使用的都是尾插法,那么他们为什么要这样做呢?因为JDK1.7是用单链表进行的纵向延伸,当采用头插法时会容易出现逆序且环形链表死循环问题。但是在JDK1.8之后是因为加入了红黑树使用尾插法,能够避免出现逆序且链表死循环的问题。

(2)扩容后数据存储位置的计算方式也不一样:1. 在JDK1.7的时候是直接用hash值和需要扩容的二进制数进行&(这里就是为什么扩容的时候为啥一定必须是2的多少次幂的原因所在,因为如果只有2的n次幂的情况时最后一位二进制数才一定是1,这样能最大程度减少hash碰撞)(hash值 & length-1)

2、而在JDK1.8的时候直接用了JDK1.7的时候计算的规律,也就是扩容前的原始位置+扩容的大小值=JDK1.8的计算方式,而不再是JDK1.7的那种异或的方法。但是这种方式就相当于只需要判断Hash值的新增参与运算的位是0还是1就直接迅速计算出了扩容后的储存方式。

在计算hash值的时候,JDK1.7用了9次扰动处理=4次位运算+5次异或,而JDK1.8只用了2次扰动处理=1次位运算+1次异或。

扩容流程对比图:

这里写图片描述

(3)JDK1.7的时候使用的是数组+ 单链表的数据结构。但是在JDK1.8及之后时,使用的是数组+链表+红黑树的数据结构(当链表的深度达到8的时候,也就是默认阈值,就会自动扩容把链表转成红黑树的数据结构来把时间复杂度从O(n)变成O(logN)提高了效率)

这里写图片描述

这里在重新进行补充两个问题:(2019-09-03)

(1)为什么在JDK1.7的时候是先进行扩容后进行插入,而在JDK1.8的时候则是先插入后进行扩容的呢?

其实就是当这个Map中实际插入的键值对的值的大小如果大于这个默认的阈值的时候(初始是16*0.75=12)的时候才会触发容,

//这个是在JDK1.8中的先插入后扩容
if (++size > threshold)resize();

其实这个问题也是JDK8对HashMap中,主要是因为对链表转为红黑树进行的优化,因为你插入这个节点的时候有可能是普通链表节点,也有可能是红黑树节点,但是为什么1.8之后HashMap变为先插入后扩容的原因,我也有点不是很理解?欢迎来讨论这个问题?
但是在JDK1.7中的话,是先进行扩容后进行插入的,就是当你发现你插入的桶是不是为空,如果不为空说明存在值就发生了hash冲突,那么就必须得扩容,但是如果不发生Hash冲突的话,说明当前桶是空的(后面并没有挂有链表),那就等到下一次发生Hash冲突的时候在进行扩容,但是当如果以后都没有发生hash冲突产生,那么就不会进行扩容了,减少了一次无用扩容,也减少了内存的使用

void addEntry(int hash, K key, V value, int bucketIndex) {//这里当钱数组如果大于等于12(假如)阈值的话,并且当前的数组的Entry数组还不能为空的时候就扩容if ((size >= threshold) && (null != table[bucketIndex])) {//扩容数组,比较耗时resize(2 * table.length);hash = (null != key) ? hash(key) : 0;bucketIndex = indexFor(hash, table.length);}createEntry(hash, key, value, bucketIndex);}void createEntry(int hash, K key, V value, int bucketIndex) {Entry<K,V> e = table[bucketIndex];//把新加的放在原先在的前面,原先的是e,现在的是new,next指向etable[bucketIndex] = new Entry<>(hash, key, value, e);//假设现在是newsize++;}

(2)为什么在JDK1.8中进行对HashMap优化的时候,把链表转化为红黑树的阈值是8,而不是7或者不是20呢(面试蘑菇街问过)?

如果选择6和8(如果链表小于等于6树还原转为链表,大于等于8转为树),中间有个差值7可以有效防止链表和树频繁转换。假设一下,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。
还有一点重要的就是由于treenodes的大小大约是常规节点的两倍,因此我们仅在容器包含足够的节点以保证使用时才使用它们,当它们变得太小(由于移除或调整大小)时,它们会被转换回普通的node节点,容器中节点分布在hash桶中的频率遵循泊松分布,桶的长度超过8的概率非常非常小。所以作者应该是根据概率统计而选择了8作为阀值

  //Java中解释的原因* Because TreeNodes are about twice the size of regular nodes, we* use them only when bins contain enough nodes to warrant use* (see TREEIFY_THRESHOLD). And when they become too small (due to* removal or resizing) they are converted back to plain bins.  In* usages with well-distributed user hashCodes, tree bins are* rarely used.  Ideally, under random hashCodes, the frequency of* nodes in bins follows a Poisson distribution* (http://en.wikipedia.org/wiki/Poisson_distribution) with a* parameter of about 0.5 on average for the default resizing* threshold of 0.75, although with a large variance because of* resizing granularity. Ignoring variance, the expected* occurrences of list size k are (exp(-0.5) * pow(0.5, k) /* factorial(k)). The first values are:** 0:    0.60653066* 1:    0.30326533* 2:    0.07581633* 3:    0.01263606* 4:    0.00157952* 5:    0.00015795* 6:    0.00001316* 7:    0.00000094* 8:    0.00000006* more: less than 1 in ten million



(二)哈希表如何解决Hash冲突?

这里写图片描述
(三)为什么HashMap具备下述特点:键-值(key-value)都允许为空、线程不安全、不保证有序、存储位置随时间变化

这里写图片描述
(四)为什么 HashMap 中 String、Integer 这样的包装类适合作为 key 键

这里写图片描述
(五)HashMap 中的 key若 Object类型, 则需实现哪些方法?

这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据技术之 Kafka (第 3 章 Kafka 架构深入 ) Kafka 消费者

3.3.1 消费方式 consumer 采用 pull&#xff08;拉&#xff09;模式从 broker 中读取数据。 push&#xff08;推&#xff09;模式很难适应消费速率不同的消费者&#xff0c;因为消息发送速率是由 broker 决定的。 它的目标是尽可能以最快速度传递消息&#xff0c;但是这样很…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) offset讲解

新版的 Kafka 使用一个选举出来的 controller 来监听 zookeeper&#xff0c;其他 node 再去和 controller 通信&#xff0c;这么做的目的是为了减少 zookeeper 的压力。bootstrap-servers 会自动发现其他 broker&#xff0c;这也是 bootstrap 的含义 前面我们讲到了消费者&…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 消费者组案例

1&#xff09;需求&#xff1a;测试同一个消费者组中的消费者&#xff0c;同一时刻只能有一个消费者消费。 2&#xff09;案例实操 &#xff08;1&#xff09;在 backupo01、backupo02 上修改/usr/local/hadoop/kafka/kafka_2.12-2.4.1/config/consumer.properties 配置 文件…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 高效读写数据

1&#xff09;顺序写磁盘 Kafka 的 producer 生产数据&#xff0c;要写入到 log 文件中&#xff0c;写的过程是一直追加到文件末端&#xff0c; 为顺序写。官网有数据表明&#xff0c;同样的磁盘&#xff0c;顺序写能到 600M/s&#xff0c;而随机写只有 100K/s。这 与磁盘的机…

大数据技术之kafka (第 3 章 Kafka 架构深入) Zookeeper 在 Kafka 中的作用

Kafka 集群中有一个 broker 会被选举为 Controller&#xff0c;负责管理集群 broker 的上下线&#xff0c;所有 topic 的分区副本分配和 leader 选举等工作。 Controller 的管理工作都是依赖于 Zookeeper 的。 以下为 partition 的 leader 选举过程&#xff1a; Leader选举流…

LinkedList源码阅分析

LinkedList里面涉及到的一些操作&#xff0c;非常细致&#xff0c;以避免出现的空指针&#xff0c;理解后对于其优点与确定会有一个更加整体的认识吧。 继承关系图(对比ArrayList) 元素的存储结构 在LinkedList中&#xff0c;每一个元素都是Node存储&#xff0c;Node拥有一个存…

取消选中目标CALL

事先在游戏里选中一个怪物bp send,回到游戏里,按ESC&#xff0c;OD断下来,复制 返回到 elementc.072AFDD8 005869B2 返回到 elementc.005869B2 来自 elementc.0058E8A0072AFDEC 00588B1F 返回到 elementc.00588B1F 来自 elementc.00586980072AFE28 005A7346 返回到 el…

《深入理解java虚拟机》第1章 走近Java

1.6实战:自己编译JDK 想要一探JDK内部的实现机制&#xff0c;最便捷的路径之一就是自己编译- -套JDK,通过阅读和跟踪调试JDK源码去了解Java技术体系的原理&#xff0c;虽然门槛会高一点&#xff0c;但肯定会比阅读各种书籍、文章更加贴近本质。另外&#xff0c;JDK中的很多底层…

《深入理解java虚拟机》第2章 Java内存区域与内存溢出异常

Java与C之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”&#xff0c;墙外面的人想进去&#xff0c;墙里面的人却想出来。 2.1 概述 https://blog.csdn.net/q5706503/article/details/84640762 对于从事C、C程序开发的开发人员来说&#xff0c;在内存管理领域&#…

线性表的定义和基本运算之线性结构

一、线性表的逻辑定义和性质 线性表是最简单和最常用的一种数据结构&#xff0c;他是由n个数据元素&#xff08;结点&#xff09;a1,a2,a3,a4........an组成的有限序列。其中&#xff0c;数据元素个数那位表的长度。当n为0时称为空表&#xff0c;非空的线性表通常记为 &#x…

数据结构之指针复习

废话不多说&#xff0c;拿起键盘就是干&#xff0c;直接上代码&#xff1a; #include <stdio.h>int main() {double *p;double x 66.6;p &x; //x占8个字节&#xff0c;一个字节占8位&#xff0c;一个字节一个地址double arr[3] { 1.1,2.2,3.3 };double *q;q &a…

数据结构之结构体复习

为什么出现结构体&#xff1f; 为了表示一些复杂的数据&#xff0c;一些基本数据类型无法满足要求&#xff0c; 当要用一个变量描述一个对象的多个属性时&#xff0c;普通的内置数据类型是表示不了的&#xff0c;这个时候就可以用结构体回。结构体和类很相似&#xff0c;唯一不…

高效管理读书笔记

高效管理读书笔记一、优秀的权威宣言二、主要的内容要点2.1 有权威的领导都会关心自己的员工2.2 问责而不指责2.3 多点尤达&#xff0c;少点超人三、原书一、优秀的权威宣言 优秀的权威就是&#xff1a; 指出大部分人视而不见的问题的气质今天畅所欲言而不是空等明天的好心【…

蒙特卡罗方法介绍(一)

蒙特卡罗方法介绍(一) 一、蒙特卡罗方法的基本思想和解题步骤 1.1 蒙特卡罗方法的基本思想 蒙特卡罗方法也称随机模拟法、随机抽样技术或统计实验发&#xff0c;其基本思想是&#xff1a;为了求解数学、物理、工程技术或生产管理等方面的问题。首先&#xff0c;建立一个与求…

神策数据张涛:如何让用户标签价值落地?

本文根据神策数据副总裁张涛在《用户个性化运营—标签体系搭建新机遇》主题沙龙中演讲整理所得。 标签系统&#xff0c;在企业中已不是什么“高大上”的说辞。然而让用户标签价值真正落地企业不多&#xff0c;就像“青少年谈性”&#xff0c; 有一段话形容得再贴切不过&#xf…

蒙特卡罗方法介绍( 二)

蒙特卡罗方法介绍( 二) 一、蒙特卡罗求解定积分 蒙特卡洛方法求解定积分有两种方法&#xff0c;一种是上一节中讲的投点法&#xff0c;另外一种是期望法&#xff08;也称平均值法&#xff09;。 1.1 投点法 给出如下曲线f(x)f(x)f(x),求f(x)f(x)f(x)在a,ba,ba,b上的积分&am…

大数据技术之kafka (第 3 章 Kafka 架构深入) 分区策略在分析

如果不懂分区策略请看我之前的文章&#xff1a;https://blog.csdn.net/ywl470812087/article/details/105328015 默认的方式我们采用的是Range策略方式&#xff08;按主题给消费者消费&#xff0c;主题被谁订阅了就谁消费&#xff09; 先看下下面这个图&#xff0c;画的很丑&a…

如何达成目标笔记

如何达成目标 一、本书主要内容 推荐序一 升级你的行动工具箱 推荐序二 人们可以改变 引言 成功者和自制力的悖论 //004 自制力到底是怎样的 //007 你能做什么 //009 本书的主题 //011 1.1 准备就绪 第1章 你明白自己去往哪里吗 别说“做到最好” //017 大局与细节 //…

大数据技术之 Kafka (第 4 章 Kafka API ) Producer API

4.1.1 消息发送流程 Kafka 的 Producer 发送消息采用的是异步发送的方式。在消息发送的过程中&#xff0c;涉及到了两个线程——main 线程和 Sender 线程&#xff0c;以及一个线程共享变量——RecordAccumulator。main 线程将消息发送给 RecordAccumulator&#xff0c;Sender…

《关键对话——何谓关键对话》读书笔记(一)

《关键对话——何谓关键对话》读书笔记&#xff08;一&#xff09; 利用假期的时间&#xff0c;将关键对话阅读了一遍&#xff0c;书中提到的观点&#xff0c;方法&#xff0c;场景等很适合我目前处的状态&#xff0c;有的时候读起来仿佛就是自己身临其境&#xff0c;有种感同身…