Hash全套总结及经典问题

1.Hashmap的扩容机制

扩容机制:

扩容(resize)就是重新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素。当然Java里的数组是无法自动扩容的,方法是使用一个新的数组代替已有的容量小的数组,就像我们用一个小桶装水,如果想装更多的水,就得换大水桶。底层是resize方法中的transfer方法将原有的Entry数组的元素拷贝到新的Entry数组里,扩容都是以2的N次幂进行扩容 一般是2倍。

2.Hash冲突

(1)开放地址法:当地址发生冲突时,按着某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止。

(2)链地址法:链地址法就是数组加链表的结合,在每一个数组元素上都有一个链表结构,当地址发生冲突时就将数据存放在链表中。

而HashMap就是采用链地址法进行解决hash冲突的。

(3)jdk1.8的HashMap中的链表达到多少个时会生成红黑树?

HashMap用链地址法解决hash冲突,则当链表里的长度太长就会严重影响HashMap的性能。于是在jdk1.8里,对数据结构做了进一步优化,引入了红黑树,当链表长度大于8的时候,链表就会转成红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,其中会用到红黑树的插入、删除、查找等算法。

3.HashMap初始值的大小和负载因子的大小?

hashMap初始长度就是16,负载因子是0.75。HashMap所容纳的最大数据量为:长度*负载因子。即当长度达到这个值的时候就会发生扩容。

4.HashMap线程安全问题

HashMap是线程不安全的,多个线程同时写HashMap可能会导致数据的不一致。如果需要满足线程安全可以用ConcurrentHashMap,还有一个HashTable。但是HashTable是继承自Dictionary类,HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下,HashTable的效率非常低下,ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成,采用segment分段锁来保证线程安全。

HashTable无论key或value都不能为null,HashMap只能允许一个key为null,可以运行多个value为null。而且HashTable是线程安全的,HashMap是线程不安全的。

5.HashMap链表成环

由于HashMap线程不安全的,至于为何不安全,什么时候会出现问题,这里来讨论一下:

当有多个线程共同操作hashMap的put方法时,这个时候hashMap容量不够了,两个线程都去扩容执行resize方法,在这个时候cpu切换资源的话,会造成链表成环问题,死循环问题。

6.Hashmap的原理

当我们往 HashMap 中 put 元素时,先根据 key 的 hash 值得到这个 Entry 元素在数组中的位置(即下标),然后把这个 Entry 元素放到对应的位置中,如果这个 Entry 元素所在的位子上已经存放有其他元素就在同一个位子上的 Entry 元素以链表的形式存放,新加入的放在链头,从 HashMap 中 get Entry 元素时先计算 key 的 hashcode,找到数组中对应位置的某一 Entry 元素,然后通过 key 的 equals 方法在对应位置的链表中找到需要的 Entry 元素,所以 HashMap 的数据结构是数组和链表的结合,此外 HashMap 中 key 和 value 都允许为 null,key 为 null 的键值对永远都放在以 table[0] 为头结点的链表中。

之所以 HashMap 这么设计的实质是由于数组存储区间是连续的,占用内存严重,故空间复杂度大,但二分查找时间复杂度小(O(1)),所以寻址容易而插入和删除困难;而链表存储区间离散,占用内存比较宽松,故空间复杂度小,但时间复杂度大(O(N)),所以寻址困难而插入和删除容易;所以就产生了一种新的数据结构叫做哈希表,哈希表既满足数据的查找方便,同时不占用太多的内容空间,使用也十分方便,哈希表有多种不同的实现方法,HashMap 采用的是链表的数组实现方式。

特别说明,对于 JDK 1.8 开始 HashMap 实现原理变成了数组+链表+红黑树的结构,数组链表部分基本不变,红黑树是为了解决哈希碰撞后链表索引效率的问题,所以在 JDK 1.8 中当链表的节点大于 8 个时就会将链表变为红黑树。区别是 JDK 1.8 以前碰撞节点会在链表头部插入,而 JDK 1.8 开始碰撞节点会在链表尾部插入,对于扩容操作后的节点转移 JDK 1.8 以前转移前后链表顺序会倒置,而 JDK 1.8 中依然保持原序。

7.TCP粘包问题

解决方法:

1.发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2.发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

3.可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

1.使用带消息头的协议、消息头存储消息开始标识及消息长度信息,服务端获取消息头的时候解析出消息长度,然后向后读取该长度的内容。
2.设置定长消息,服务端每次读取既定长度的内容作为一条完整消息,当消息不够长时,空位补上固定字符。
3.设置消息边界,服务端从网络流中按消息编辑分离出消息内容,一般使用‘\n’。

8.三次握手、四次挥手

三次握手解释下
发送请求之前,先建立连接
第一次:客户端向服务端发送建立连接请求
第二次:服务端向客户端返回响应
第三次:客户端向服务端返回已建立连接确认请求

三次握手:

举个栗子:把客户端比作男孩,服务器比作女孩。用他们的交往来说明“三次握手”过程:

(1)男孩喜欢女孩,于是写了一封信告诉女孩:我爱你,请和我交往吧!;写完信之后,男孩焦急地等待,因为不知道信能否顺利传达给女孩。

(2)女孩收到男孩的情书后,心花怒放,原来我们是两情相悦呀!于是给男孩写了一封回信:我收到你的情书了,也明白了你的心意,其实,我也喜欢你!我愿意和你交往!;

写完信之后,女孩也焦急地等待,因为不知道回信能否能顺利传达给男孩。

(3)男孩收到回信之后很开心,因为发出的情书女孩收到了,并且从回信中知道了女孩喜欢自己,并且愿意和自己交往。然后男孩又写了一封信告诉女孩:你的心意和信我都收到了,谢谢你,还有我爱你!

女孩收到男孩的回信之后,也很开心,因为发出的情书男孩收到了。由此男孩女孩双方都知道了彼此的心意,之后就快乐地交流起来了

四次挥手:

举个栗子:把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程。

“第一次挥手”:日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。

“第二次挥手”:女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。

“第三次挥手”:过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!

“第四次挥手”:男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!

这里双方都有各自的坚持。

女孩自发出第二封信开始,限定一天内收不到男孩回信,就会再发一封信催促男孩来取东西!

男孩自发出第二封信开始,限定两天内没有再次收到女孩的信就认为,女孩收到了自己的第二封信;若两天内再次收到女孩的来信,就认为自己的第二封信女孩没收到,需要再写一封信,再等两天……

倘若双方信都能正常收到,最少只用四封信就能彻底分手!这就是“四次挥手”。

9.为什么“握手”是三次,“挥手”却要四次?

TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。

即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。

TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?

建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。所以是“三次握手”,“四次挥手”

10.流量控制与拥塞控制

流量控制:如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。

TCP的流量控制是利用滑动窗口机制实现的,接收方在返回的数据中会包含自己的接收窗口的大小,以控制发送方的数据发送。

拥塞控制:拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。

两者的区别:流量控制是为了预防拥塞。如:在马路上行车,交警跟红绿灯是流量控制,当发生拥塞时,如何进行疏散,是拥塞控制。流量控制指点对点通信量的控制。而拥塞控制是全局性的,涉及到所有的主机和降低网络性能的因素。

11.get与post的区别

那么很明显 GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。

POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。

12.Https和Http的区别

(1)HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。

(2)HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。

(3)HTTP 的端口号是 80,HTTPS 的端口号是 443。

(4)HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTPS 采用的是对称加密非对称加密结合的「混合加密」方式:

  • 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。

采用「混合加密」的方式的原因:

  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

13.TCP与UDP的区别:

(1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

(2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

(3)TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

(4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

(5)TCP首部开销20字节;UDP的首部开销小,只有8个字节

(6)TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

简化版

TCP 是面向连接的,UDP 是面向无连接的
UDP程序结构较简单
TCP 是面向字节流的,UDP 是基于数据报的
TCP 保证数据正确性,UDP 可能丢包
TCP 保证数据顺序,UDP 不保证

14.什么是面向连接,什么是面向无连接?

在互通之前,面向连接的协议会先建立连接,如TCP有三次握手,而 UDP不会

15.TCP 为什么是可靠连接

通过 TCP 连接传输的数据无差错,不丢失,不重复,且按顺序到达。
TCP 报文头里面的序号能使 TCP 的数据按序到达
报文头里面的确认序号能保证不丢包,累计确认及超时重传机制
TCP 拥有流量控制及拥塞控制的机制

TCP 的顺序问题,丢包问题,流量控制都是通过滑动窗口来解决的
拥塞控制时通过拥塞窗口来解决的

1.联合索引和主键索引区别

主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字 PRIMARY KEY 来创建。 索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引,这就是联合索引。

主键分为复合主键和联合主键

复合主键就是指你表的主键含有一个以上的字段组成。例如;

create table test ( name varchar(19), id number, value varchar(10), primary key (id,name) )

上面的id和name字段组合起来就是你test表的复合主键 (若其一为单索引字段时,左边的id才会有索引) 它的出现是因为你的name字段可能会出现重名,所以要加上ID字段这样就可以保证你记录的唯一性,一般情况下,主键的字段长度和字段数目要越少越好

联合主键,顾名思义就是多个主键联合形成一个主键组合,体现在联合。 (主键原则上是唯一的,别被唯一值所困扰。) 索引可以极大的提高数据的查询速度,但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件。 简单的例子,主键A跟主键B组成联合主键,主键A跟主键B的数据可以完全相同(困扰吧,没关系),联合就在于主键A跟主键B形成的联合主键是唯一的。

2.主键索引和唯一索引的区别:
(1) 对于主键/unique constraint,oracle/sql server/mysql等都会自动建立唯一索引;
(2) 主键不一定只包含一个字段,所以在主键的其中一个字段建唯一索引还是有必要的;
(3) 主键可作外键,唯一索引不可;
(4) 主键不可为空,唯一索引可;
(5) 主键可是多个字段的组合;
(6) 主键与唯一索引不同的是: a.有not null属性;b.每个表只能有一个。
(7) 主键索引一定是唯一索引, 唯一索引不是主键索引
(8) 主键可以与外键构成参照完整性约束,防止数据不一致

3.sql题:有readerid,bookid,tagid,查出指定bookid最热门的10个标签,readerid越多,越热门

我的答案是这个

select tagid from tb where bookid=1 group by tagid order by count(readerid) desc limit 10

4.你做过的最有成就的事情是什么

完成一个科技厅项目

5.你的未来规划

今年我是想要拿到大厂的实习offer,如果可以顺利拿到offer的话, 会想要从中学习一些专业的知识,对整个互联网行业的了解得到一定的提升。然后了解自己的行业背景,以及自已未来的发展方向,未来二至三年希望自己可以以学习和提升自己为主,可以实现自己在公司的价值。

6.兴趣爱好

唱歌、打球、健身

7.甚至聊到社会发展、看法

内卷和努力的看法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值