Skip to content

Commit 1632009

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 6af2961 + b7f628c commit 1632009

2 files changed

+10
-10
lines changed

docs/md/java/interview/2020-08-07-面经手册 · 第3篇《HashMap核心知识,扰动函数、负载因子、扩容链表拆分,深度学习》.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,10 @@ public HashMap(int initialCapacity, float loadFactor) {
236236
}
237237
```
238238

239-
- 阀值`threshold`,通过方法`tableSizeFor`进行计算,是根据初始化来计算的。
239+
- 阈值`threshold`,通过方法`tableSizeFor`进行计算,是根据初始化来计算的。
240240
- 这个方法也就是要寻找比初始值大的,最小的那个2进制数值。比如传了17,我应该找到的是32。
241241

242-
计算阀值大小的方法
242+
计算阈值大小的方法
243243

244244
```java
245245
static final int tableSizeFor(int cap) {
@@ -256,9 +256,9 @@ static final int tableSizeFor(int cap) {
256256
- MAXIMUM_CAPACITY = 1 << 30,这个是临界范围,也就是最大的Map集合。
257257
- 乍一看可能有点晕😵怎么都在向右移位1、2、4、8、16,这主要是为了把二进制的各个位置都填上1,当二进制的各个位置都是1以后,就是一个标准的2的倍数减1了,最后把结果加1再返回即可。
258258

259-
那这里我们把17这样一个初始化计算阀值的过程,用图展示出来,方便理解;
259+
那这里我们把17这样一个初始化计算阈值的过程,用图展示出来,方便理解;
260260

261-
![bugstack.cn 计算阀值](https://bugstack.cn/assets/images/2020/interview/interview-4-05.png)
261+
![bugstack.cn 计算阈值](https://bugstack.cn/assets/images/2020/interview/interview-4-05.png)
262262

263263
#### 3.2 负载因子
264264

@@ -268,17 +268,17 @@ static final float DEFAULT_LOAD_FACTOR = 0.75f;
268268

269269
**负载因子是做什么的?**
270270

271-
负载因子,可以理解成一辆车可承重重量超过某个阀值时,把货放到新的车上。
271+
负载因子,可以理解成一辆车可承重重量超过某个阈值时,把货放到新的车上。
272272

273273
那么在HashMap中,负载因子决定了数据量多少了以后进行扩容。*这里要提到上面做的HashMap例子,我们准备了7个元素,但是最后还有3个位置空余,2个位置存放了2个元素。* 所以可能即使你数据比数组容量大时也是不一定能正正好好的把数组占满的,而是在某些小标位置出现了大量的碰撞,只能在同一个位置用链表存放,那么这样就失去了Map数组的性能。
274274

275-
所以,要选择一个合理的大小下进行扩容,默认值0.75就是说当阀值容量占了3/4时赶紧扩容,减少Hash碰撞。
275+
所以,要选择一个合理的大小下进行扩容,默认值0.75就是说当阈值容量占了3/4时赶紧扩容,减少Hash碰撞。
276276

277277
同时0.75是一个默认构造值,在创建HashMap也可以调整,比如你希望用更多的空间换取时间,可以把负载因子调的更小一些,减少碰撞。
278278

279279
### 4. 扩容元素拆分
280280

281-
为什么扩容,因为数组长度不足了。那扩容最直接的问题,就是需要把元素拆分到新的数组中。拆分元素的过程中,原jdk1.7中会需要重新计算哈希值,但是到jdk1.8中已经进行优化,不在需要重新计算,提升了拆分的性能,设计的还是非常巧妙的。
281+
为什么扩容,因为数组长度不足了。那扩容最直接的问题,就是需要把元素拆分到新的数组中。拆分元素的过程中,原jdk1.7中会需要重新计算哈希值,但是到jdk1.8中已经进行优化,不再需要重新计算,提升了拆分的性能,设计的还是非常巧妙的。
282282

283283
#### 4.1 测试数据
284284

docs/md/java/interview/2021-03-07-面试现场:小伙伴美团一面的分享和分析[含解答].md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public class Singleton {
7777

7878
**可见性**
7979

80-
- 首选,volatile 关键字修饰的共享变量可以提供这种可见性规范,也叫做读写可见。
80+
- 首先,volatile 关键字修饰的共享变量可以提供这种可见性规范,也叫做读写可见。
8181
- 被 volatile 关键字修饰的共享变量在转换成汇编语言时,会加上一个以 lock 为前缀的指令,当CPU发现这个指令时,立即将当前内核高速缓存行的数据回写到内存,同时使在其他内核里缓存了该内存地址的数据无效。
8282
- 另外,在早期的 CPU 中,是通过在总线加 LOCK# 锁的方式实现的,但这种方式开销较大。所以Intel开发了缓存一致性协议,也就是 MESI 协议,该解决缓存一致性。
8383
- `volatile 的好处`,volatile 是一种非锁机制,这种机制可以避免锁机制引起的线程上下文切换和调度问题。所以,volatile 的执行成本比 synchronized 更低。
@@ -161,7 +161,7 @@ public void test() {
161161
| 维护性 | 基于 Java 和 Scala 语言 实现,社区活跃度高,维护成本较低 | 基于 Java 语言实现,社区活跃度高,维护成本较低 | 基于 Java 语言实现,消息队列场景功能很完备,但社区活跃度较低,维护成本较高 | 基于 erlang 语言开发,社区活跃度一般,小团队维护成本较高 |
162162

163163
- 首先要知道,开源社区有很多优秀的队列中间件,比如 RabbitMQ、ActiveMQ、RocketMQ、Kafka,有些大厂还有自研的 MQ 队列中间件。
164-
- 解耦、消峰、驱动等场景下的业务时以及日志采集系统、监控系统、流式处理等各类场景中都离不开MQ队列。
164+
- 解耦、削峰、驱动等场景下的业务时以及日志采集系统、监控系统、流式处理等各类场景中都离不开MQ队列。
165165

166166
12. `你觉得对于一个消息中间件来说,需要达到哪些要求?`
167167

@@ -191,5 +191,5 @@ public void test() {
191191
## 三、总结
192192

193193
- 如果你不希望面试时自己的薪资、待遇、职位,被别人安排来摆弄去,就要不断的在开发过程中提炼、总结、归纳自己的知识项,找到个人的价值力量,不断的去扩宽和加深。
194-
- 我特别同意本文我的小伙伴的总结,也是此次求职者的分享;“程序员不是一个木偶人,不只是被动的接需求或者任务,也不能知识埋头苦干”。公司是没有永远稳定的,互联网的变化也更多,只有自己拥有了留下的本事和走出去的能力,才是个人的最安全区域。
194+
- 我特别同意本文我的小伙伴的总结,也是此次求职者的分享;“程序员不是一个木偶人,不只是被动的接需求或者任务,也不能只是埋头苦干”。公司是没有永远稳定的,互联网的变化也更多,只有自己拥有了留下的本事和走出去的能力,才是个人的最安全区域。
195195
- 最后希望每一个研发小伙伴都能有所积累和沉淀,把那些视频当电影、看文章当小说的毛病改改,要学会动起来,验证起来,实践才能让一个知识更能落到自己的脑子里。

0 commit comments

Comments
 (0)