Skip to content

Commit 82e8832

Browse files
committed
奇安信
1 parent 2167785 commit 82e8832

File tree

5 files changed

+179
-35
lines changed

5 files changed

+179
-35
lines changed

docs/sidebar/sanfene/collection.md

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,13 @@ BlockingQueue 接口的实现类有 ArrayBlockingQueue、DelayQueue、LinkedBloc
7272

7373
阻塞指的是一种程序执行状态,其中某个线程在等待某个条件满足时暂停其执行(即阻塞),直到条件满足时恢复其执行。
7474

75-
推荐阅读:[阻塞队列BlockingQueue](https://javabetter.cn/thread/BlockingQueue.html)
76-
75+
推荐阅读:[阻塞队列 BlockingQueue](https://javabetter.cn/thread/BlockingQueue.html)
7776

7877
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的用友金融一面原题:你了解哪些集合框架?
7978
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为一面原题:说下 Java 容器和 HashMap
8079
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米暑期实习同学 E 一面面试原题:你了解哪些集合?
8180
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的美团面经同学 16 暑期实习一面面试原题:知道哪些集合,讲讲 HashMap 和 TreeMap 的区别,讲讲两者应用场景的区别;讲一下有哪些队列,阻塞队列的阻塞是什么含义?
8281
83-
8482
## List
8583

8684
### 2.ArrayList 和 LinkedList 有什么区别?
@@ -582,11 +580,15 @@ $2^n$ 的二进制形式为 1,后面跟着 n 个 0,那 $2^n$ - 1 的二进
582580
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米春招同学 K 一面面试原题:为什么是 2 次幂 到什么时候开始扩容 扩容机制流程
583581
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的支付宝面经同学 2 春招技术一面面试原题:hashCode 对数组长度取模定位数组下标,这块有没有优化策略?
584582
585-
### 16.如果初始化 HashMap,传一个 17 的值`new HashMap<>`,它会怎么处理?
583+
### 16.如果初始化 HashMap,传一个 17 容量,它会怎么处理?
584+
585+
HashMap 会将这个值转换为大于或等于 17 的最小的 2 的幂。这是因为 HashMap 的设计是基于哈希表的,而哈希表的大小最好是 2 的幂,这样可以优化哈希值的计算,并减少哈希冲突。
586+
587+
所以,如果你传入 17 作为初始容量,HashMap 实际上会被初始化为大小为 32 的哈希表。
586588

587-
简单来说,就是初始化时,传的不是 2 的倍数时,HashMap 会向上寻找`离得最近的2的倍数`,所以传入 17,但 HashMap 的实际容量是 32。
589+
![三分恶面渣逆袭:容量计算](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/collection-18.png)
588590

589-
我们来看看详情,在 HashMap 的初始化中,有这样⼀段⽅法;
591+
在 HashMap 的初始化构造方法中,有这样⼀段代码:
590592

591593
```java
592594
public HashMap(int initialCapacity, float loadFactor) {
@@ -596,26 +598,45 @@ public HashMap(int initialCapacity, float loadFactor) {
596598
}
597599
```
598600

599-
- 阀值 threshold ,通过⽅法` tableSizeFor` 进⾏计算,是根据初始化传的参数来计算的。
600-
- 同时,这个⽅法也要要寻找⽐初始值⼤的,最⼩的那个 2 进制数值。⽐如传了 17,我应该找到的是 32。
601+
阀值 threshold 会通过⽅法` tableSizeFor()` 进⾏计算。
601602

602603
```java
603604
static final int tableSizeFor(int cap) {
604-
int n = cap - 1;
605-
n |= n >>> 1;
606-
n |= n >>> 2;
607-
n |= n >>> 4;
608-
n |= n >>> 8;
609-
n |= n >>> 16;
610-
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; }
605+
int n = cap - 1;
606+
n |= n >>> 1;
607+
n |= n >>> 2;
608+
n |= n >>> 4;
609+
n |= n >>> 8;
610+
n |= n >>> 16;
611+
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
612+
}
611613
```
612614

613-
- MAXIMUM_CAPACITY = 1 << 30,这个是临界范围,也就是最⼤的 Map 集合。
614-
- 计算过程是向右移位 1、2、4、8、16,和原来的数做`|`运算,这主要是为了把⼆进制的各个位置都填上 1,当⼆进制的各个位置都是 1 以后,就是⼀个标准的 2 的倍数减 1 了,最后把结果加 1 再返回即可。
615+
①、`int n = cap - 1;` 将传入的容量减 1,用于确保如果传入的容量已经是 2 的幂次方,计算结果不会超过这个数。
616+
617+
②、接下来通过不断右移(`>>>`)并与自身进行或运算(`|=`),将 n 的二进制表示中的所有低位设置为 1。
618+
619+
- `n |= n >>> 1;` 把 n 的二进制表示中最高位的 1 之后的一个 0 变成 1。
620+
- `n |= n >>> 2;` 接着把后两位中的 0 都变成 1。
621+
- 依此类推,直到 `n |= n >>> 16;`,此时 n 的二进制表示中,从最高位的 1 开始到最低位,都变成了 1。
622+
623+
③、如果 n 小于 0,说明 cap 是负数,直接返回 1(理论上哈希表的大小不应该是负数或 0)。
615624

616-
以 17 为例,看一下初始化计算 table 容量的过程:
625+
如果 n 大于或等于 MAXIMUM_CAPACITY(通常是$2^{30}$),则返回 MAXIMUM_CAPACITY。
617626

618-
![容量计算](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/sidebar/sanfene/collection-18.png)
627+
否则,返回 n + 1,这是因为 n 的所有低位都是 1,所以 n + 1 就是大于 cap 的最小的 2 的幂次方。
628+
629+
#### 初始化 HashMap 的时候需要传入容量值吗?
630+
631+
在创建 HashMap 时可以指定初始容量值。这个容量是指 Map 内部用于存储数据的数组大小。
632+
633+
如果预先知道 Map 将存储大量键值对,提前指定一个足够大的初始容量可以减少因扩容导致的重哈希(rehashing)操作,从而提高性能。
634+
635+
因为每次扩容时,HashMap 需要新分配一个更大的数组并重新将现有的元素插入到这个新数组中,这个过程相对耗时,尤其是当 Map 中已有大量数据时。
636+
637+
当然了,过大的初始容量会浪费内存,特别是当实际存储的元素远少于初始容量时。如果不指定初始容量,HashMap 将使用默认的初始容量 16。
638+
639+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:map 集合在使用时候一般都需要写容量值?为什么要写?扩容机制?
619640
620641
### 17.你还知道哪些哈希函数的构造方法呢?
621642

@@ -844,7 +865,7 @@ final int hash(Object k) {
844865

845866
当然了,这个功劳既属于新的哈希算法,也离不开 n 为 2 的整数次幂这个前提,这是它俩通力合作后的结果 `hash & (newCapacity - 1)`
846867

847-
#### 那你说说扩容的时候每个节点都要进行位运算吗,如果我这个HashMap里面有几十万条数据,都要进行位运算吗?
868+
#### 那你说说扩容的时候每个节点都要进行位运算吗,如果我这个 HashMap 里面有几十万条数据,都要进行位运算吗?
848869

849870
在 JDK 8 的新 hash 算法下,数组扩容后的索引位置,要么就是原来的索引位置,要么就是“原索引+原来的容量”,遵循一定的规律。
850871

@@ -853,7 +874,8 @@ final int hash(Object k) {
853874
所以,尽管有几十万条数据,每个数据项的位置决定仅需要一次简单的位运算。位运算的计算速度非常快,因此,尽管扩容操作涉及遍历整个哈希表并对每个节点进行操作,但这部分操作的计算成本是相对较低的。
854875

855876
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米春招同学 K 一面面试原题:为什么是 2 次幂 到什么时候开始扩容 扩容机制流程
856-
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米暑期实习同学 E 一面面试原题:说说HashMap的扩容机制,1.8扩容具体实现
877+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米暑期实习同学 E 一面面试原题:说说 HashMap 的扩容机制,1.8 扩容具体实现
878+
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:map 集合在使用时候一般都需要写容量值?为什么要写?扩容机制?
857879
858880
### 22.jdk1.8 对 HashMap 主要做了哪些优化呢?为什么?
859881

@@ -920,7 +942,7 @@ HashMap 不是线程安全的,主要有以下几个问题:
920942
因为线程 1 执行完 table = newTab 之后,线程 2 中的 table 此时也发生了变化,此时去 get 的时候当然会 get 到 null 了,因为元素还没有转移。
921943

922944
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为 OD 原题:HashMap 是线程安全的吗?
923-
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为面经同学 8 技术二面面试原题:HashMap是线程安全的吗
945+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为面经同学 8 技术二面面试原题:HashMap 是线程安全的吗
924946
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 9 飞书后端技术一面面试原题:HashMap 为什么不安全,如何改进,以及 ConcurrentHashMap
925947
926948
### 25.有什么办法能解决 HashMap 线程不安全的问题呢?
@@ -944,10 +966,9 @@ Hashtable 也是线程安全的,但它的使用已经不再推荐使用,因
944966
![初念初恋:ConcurrentHashMap 8 中的实现](https://cdn.tobebetterjavaer.com/stutymore/map-20230816155924.png)
945967

946968
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米春招同学 K 一面面试原题:有哪些线程安全的 map,ConcurrentHashMap 怎么保证线程安全的,为什么比 hashTable 效率好
947-
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为面经同学 8 技术二面面试原题:Java中的线程安全的集合是什么
969+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的华为面经同学 8 技术二面面试原题:Java 中的线程安全的集合是什么
948970
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动面经同学 9 飞书后端技术一面面试原题:HashMap 为什么不安全,如何改进,以及 ConcurrentHashMap
949971
950-
951972
### 27.HashMap 内部节点是有序的吗?
952973

953974
HashMap 是无序的,根据 hash 值随机插入。如果想使用有序的 Map,可以使用 LinkedHashMap 或者 TreeMap。

docs/sidebar/sanfene/mysql.md

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
title: MySQL面试题,69道MySQL八股文(1.8万字69张手绘图),面渣逆袭必看👍
2+
title: MySQL面试题,70道MySQL八股文(1.8万字69张手绘图),面渣逆袭必看👍
33
shortTitle: 面渣逆袭-MySQL
4-
description: 下载次数超 1 万次,1.8 万字 69 张手绘图,详解 69 道 MySQL 面试高频题(让天下没有难背的八股),面渣背会这些 MySQL 八股文,这次吊打面试官,我觉得稳了(手动 dog)。
4+
description: 下载次数超 1 万次,1.8 万字 69 张手绘图,详解 70 道 MySQL 面试高频题(让天下没有难背的八股),面渣背会这些 MySQL 八股文,这次吊打面试官,我觉得稳了(手动 dog)。
55
author: 三分恶
66
category:
77
- 面渣逆袭
@@ -13,7 +13,7 @@ head:
1313
content: MySQL面试题,MySQL,mysql,面试题,八股文
1414
---
1515

16-
1.8 万字 69 张手绘图,详解 69 道 MySQL 面试高频题(让天下没有难背的八股),面渣背会这些 MySQL 八股文,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/JFjFs_7xduCmHOegbJ-Gbg),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/zSTyZ-8CFalwAYSB0PN6wA)
16+
1.8 万字 101 张手绘图,详解 70 道 MySQL 面试高频题(让天下没有难背的八股),面渣背会这些 MySQL 八股文,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/JFjFs_7xduCmHOegbJ-Gbg),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/zSTyZ-8CFalwAYSB0PN6wA)
1717

1818
### 0.什么是 MySQL?
1919

@@ -1378,7 +1378,7 @@ MySQL 的默认存储引擎是 InnoDB,它采用的是 B+树索引,B+树是
13781378
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动商业化一面的原题:说说 B+树,为什么 3 层容纳 2000W 条,为什么 2000w 条数据查的快
13791379
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的国企面试原题:说说 MySQL 的底层数据结构,B 树和 B+树的区别
13801380
> 3. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的腾讯面经同学 22 暑期实习一面面试原题:MySQL 为什么选用 B+树
1381-
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米面经同学 E 第二个部门 Java 后端技术一面面试原题:说一说mysql索引的底层机制
1381+
> 4. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的小米面经同学 E 第二个部门 Java 后端技术一面面试原题:说一说 mysql 索引的底层机制
13821382
13831383
### 34.那一棵 B+树能存储多少条数据呢?
13841384

@@ -1394,7 +1394,18 @@ MySQL 的默认存储引擎是 InnoDB,它采用的是 B+树索引,B+树是
13941394

13951395
理论上,在 InnoDB 存储引擎中,B+树的高度一般为 2-4 层,就可以满足千万级数据的存储。查找数据的时候,一次页的查找代表一次 IO,当我们通过主键索引查询的时候,最多只需要 2-4 次 IO 就可以了。
13961396

1397+
#### innodb 使用数据页存储数据?默认数据页大小 16K,我现在有一张表,有 2kw 数据,我这个 b+树的高度有几层?
1398+
1399+
InnoDB 存储引擎使用 B+树作为索引结构,数据页是 B+树中的节点。默认的数据页大小为 16KB。
1400+
1401+
B+树的高度取决于每个数据页(节点)可以存放的键值对数量。这个数量又取决于键和值的大小。假设每个键值对占用 100 字节,那么一个 16KB 的数据页大约可以存放约 160 个键值对(实际上会稍少一些,因为还需要考虑到一些额外的开销)。
1402+
1403+
如果你有 200 万(2KW)条数据,那么理论上需要的数据页数量就是 2000000 / 160 = 12500 页。这是在假设所有数据都能均匀分布在所有数据页中的情况下。
1404+
1405+
至于 B+树的高度,取决于树的分支因子(即每个节点的子节点数量)。假设分支因子为 400(这是一个估计值,实际值取决于许多因素),那么一个有 12500 页的 B+树的高度大约为 3 层。
1406+
13971407
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的字节跳动商业化一面的原题:说说 B+树,为什么 3 层容纳 2000W 条,为什么 2000w 条数据查的快
1408+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:innodb 使用数据页存储数据?默认数据页大小 16K,我现在有一张表,有 2kw 数据,我这个 b+树的高度有几层?
13981409
13991410
### 35.为什么要用 B+ 树,而不用普通二叉树?
14001411

@@ -1435,6 +1446,7 @@ B+树的所有值(数据记录或指向数据记录的指针)都存在于叶
14351446
B+树中所有叶子节点深度相同,所有数据查询路径长度相等,保证了每次搜索的性能稳定性。而在 B 树中,数据可以存储在内部节点,不同的查询可能需要不同深度的搜索。
14361447

14371448
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的支付宝面经同学 2 春招技术一面面试原题:聚簇索引和非聚簇索引的区别?B+树叶子节点除了存数据还有什么?
1449+
> 2. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:b 树和 b+树有什么区别
14381450
14391451
### 37.Hash 索引和 B+ 树索引区别是什么?
14401452

@@ -2284,7 +2296,82 @@ GitHub 上标星 10000+ 的开源知识库《[二哥的 Java 进阶之路](https
22842296

22852297
也有可能是每个 sql 消耗资源并不多,但是突然之间,有大量的 session 连进来导致 cpu 飙升,这种情况就需要跟应用一起来分析为何连接数会激增,再做出相应的调整,比如说限制连接数等
22862298

2287-
> 图文详解 69 道 MySQL 面试高频题,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/JFjFs_7xduCmHOegbJ-Gbg),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/zSTyZ-8CFalwAYSB0PN6wA)
2299+
## SQL 题
2300+
2301+
### 70.一张表:id,name,age,sex,class,sql 语句:所有年龄为 18 的人的名字?找到每个班年龄大于 18 有多少人?找到每个班年龄排前两名的人?
2302+
2303+
> 这是一道 SQL 题,主要考察 SQL 的基本语法。建议大家直接在本地建表,然后实操一下。
2304+
2305+
第一步,建表:
2306+
2307+
```sql
2308+
CREATE TABLE students (
2309+
id INT AUTO_INCREMENT PRIMARY KEY,
2310+
name VARCHAR(50),
2311+
age INT,
2312+
sex CHAR(1),
2313+
class VARCHAR(50)
2314+
);
2315+
```
2316+
2317+
第二步,插入数据:
2318+
2319+
```sql
2320+
INSERT INTO students (name, age, sex, class) VALUES
2321+
('沉默王二', 18, '', '三年二班'),
2322+
('沉默王一', 20, '', '三年二班'),
2323+
('沉默王三', 19, '', '三年三班'),
2324+
('沉默王四', 17, '', '三年三班'),
2325+
('沉默王五', 20, '', '三年四班'),
2326+
('沉默王六', 21, '', '三年四班'),
2327+
('沉默王七', 18, '', '三年四班');
2328+
```
2329+
2330+
①、所有年龄为 18 的人的名字
2331+
2332+
```sql
2333+
SELECT name FROM students WHERE age = 18;
2334+
```
2335+
2336+
这条 SQL 语句从表中选择`age`等于 18 的所有记录,并返回这些记录的`name`字段。
2337+
2338+
![二哥的 Java 进阶之路](https://cdn.tobebetterjavaer.com/stutymore/mysql-20240410105325.png)
2339+
2340+
②、找到每个班年龄大于 18 有多少人
2341+
2342+
```sql
2343+
SELECT class, COUNT(*) AS number_of_students
2344+
FROM students
2345+
WHERE age > 18
2346+
GROUP BY class;
2347+
```
2348+
2349+
这条 SQL 语句先筛选出年龄大于 18 的记录,然后按`class`分组,并计算每个班的学生数。
2350+
2351+
![二哥的 Java 进阶之路](https://cdn.tobebetterjavaer.com/stutymore/mysql-20240410105512.png)
2352+
2353+
③、找到每个班年龄排前两名的人
2354+
2355+
这个查询稍微复杂一些,需要使用子查询和`COUNT`函数。
2356+
2357+
```sql
2358+
SELECT a.class, a.name, a.age
2359+
FROM students a
2360+
WHERE (
2361+
SELECT COUNT(DISTINCT b.age)
2362+
FROM students b
2363+
WHERE b.class = a.class AND b.age > a.age
2364+
) < 2
2365+
ORDER BY a.class, a.age DESC;
2366+
```
2367+
2368+
这条 SQL 语句首先从`students`表中选择`class``name``age`字段,然后使用子查询计算每个班级中年龄排前两名的学生。
2369+
2370+
![二哥的 Java 进阶之路](https://cdn.tobebetterjavaer.com/stutymore/mysql-20240410105951.png)
2371+
2372+
> 1. [Java 面试指南(付费)](https://javabetter.cn/zhishixingqiu/mianshi.html)收录的奇安信面经同学 1 Java 技术一面面试原题:一张表:id,name,age,sex,class,sql 语句:所有年龄为 18 的人的名字?找到每个班年龄大于 18 有多少人?找到每个班年龄排前两名的人?
2373+
2374+
> 图文详解 70 道 MySQL 面试高频题,这次吊打面试官,我觉得稳了(手动 dog)。整理:沉默王二,戳[转载链接](https://mp.weixin.qq.com/s/JFjFs_7xduCmHOegbJ-Gbg),作者:三分恶,戳[原文链接](https://mp.weixin.qq.com/s/zSTyZ-8CFalwAYSB0PN6wA)
22882375
22892376
---
22902377

0 commit comments

Comments
 (0)