当前位置: 首页 > news >正文

面试常问笔记整理

MySQL

一、MySQL 操作的四大特性通常指的是ACID。

1. 原子性(Atomicity)

原子性要求事务中的所有操作 “要么全部执行,要么全部不执行”,不存在部分完成的中间状态。

  • 例如,转账操作中 “扣款” 和 “收款” 两个步骤必须同时成功或同时失败。
  • 若过程中发生错误(如网络中断),数据库会回滚(Rollback)到事务开始前的状态,避免出现 “钱扣了但没到账” 的情况。

2. 一致性(Consistency)

一致性确保事务执行前后,数据库的完整性约束(如主键唯一、字段非空、外键关联)不被破坏,数据始终处于合法状态。

  • 例如,一个字段定义为 “年龄” 且只能是正整数,事务中不能将其更新为负数或字符串。
  • 即使事务执行失败并回滚,数据也会保持符合规则的初始一致状态。

3. 隔离性(Isolation)

隔离性控制多个并发事务之间的相互影响,防止一个事务的操作结果被其他未完成的事务干扰。

  • MySQL 通过 “隔离级别” 实现隔离性,从低到高包括:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read,MySQL 默认)、串行化(Serializable)。
  • 例如,在 “读已提交” 级别下,事务 A 看不到事务 B 未提交的修改,避免出现 “脏读”(读取到未最终确认的数据)。

4. 持久性(Durability)

持久性保证一旦事务执行成功并提交(Commit),其对数据的修改会被永久保存,即使后续发生数据库崩溃、服务器断电等故障也不会丢失。

  • MySQL 通过 “重做日志(Redo Log)” 实现持久性,事务提交时会先将修改记录到重做日志,再写入磁盘数据文件。
  • 即使数据文件写入未完成时服务器宕机,重启后数据库也能通过重做日志恢复已提交的事务。

二. MySQL 四大事务隔离级别

  • 读未提交(Read Uncommitted):最低隔离级别,允许读取其他事务未提交的修改,可能导致 “脏读”“不可重复读”“幻读”。
  • 读已提交(Read Committed):只能读取其他事务已提交的修改,避免 “脏读”,但仍可能出现 “不可重复读” 和 “幻读”,是许多数据库的默认级别。
  • 可重复读(Repeatable Read):MySQL 默认级别,确保同一事务内多次读取同一数据的结果一致,避免 “脏读” 和 “不可重复读”,通过 Next-Key Lock 机制减少 “幻读”。
  • 串行化(Serializable):最高隔离级别,强制事务串行执行(不并发),完全避免所有并发问题,但性能极低,仅用于数据一致性要求极高的特殊场景。

三、MySQL 四大常用索引类型

  • 主键索引(Primary Key):唯一标识表中每条记录,一个表只能有一个主键索引,且索引列值不允许为 NULL。
  • 唯一索引(Unique Index):确保索引列的值在表中唯一,但允许为 NULL(多个 NULL 值不冲突),常用于手机号、邮箱等唯一标识字段。
  • 普通索引(Normal Index):最基础的索引,仅用于加速查询,不限制索引列的值是否唯一或为 NULL,适用于频繁作为查询条件的字段。
  • 联合索引(Composite Index):基于多个列创建的索引,遵循 “最左前缀原则”,适用于多列组合查询的场景(如 “用户名 + 手机号” 联合查询)。

HashMap

一、HashMap的put方法

  1. HashMap存储的是键值对;
  2. 首先计算Key的哈希值,减少哈希冲突;
  3. 再通过哈希值去计算他的索引位置;
  4. 得到索引位置会出现两种情况,索引位置为空,或者不为空,不为空就是存在单节点,链表或者红黑树;
  5. 我们先说为空的情况,为空的话直接创建节点插入即可;
  6. 如果不为空,是单节点的话我们判断一下该节点的Key值和我们的Key是否相同,如果相同直接覆盖就可以了;
  7. 不相同就是链表或者红黑树;
  8. 是链表我们就遍历链表,看看有没有重复Key,有就覆盖,没有就从链表尾部插入;
  9. 这个时候需要注意链表长度是否超过8,超过的话需要将链表转化为红黑树;
  10. 如果是红黑树的花我们也是如此,有相同key就覆盖,没有就用树的插入方法插入新节点。
  11. 最后有一个扩容判断吧,当插入后如果元素数量超过负载因子*数组长度,就会对当前集合进行扩容。
  12. 长度翻倍,哈希值和索引位置重新计算。

二、核心方法

1、核心操作方法(增删改查)

1. V put(K key, V value)
  • 功能:插入键值对,若 key 已存在则覆盖旧 value,返回旧值(无旧值则返回 null)。
  • 底层逻辑
    • 计算 key 的哈希值,确定数组索引。
    • 处理哈希冲突(链表 / 红黑树插入),必要时触发扩容(resize())。
  • 注意:key 可为 null(固定存放在索引 0 位置)。
2. V get(Object key)
  • 功能:根据 key 获取对应的 value,若 key 不存在则返回 null。
  • 底层逻辑
    • 计算 key 的哈希值和索引,遍历对应位置的链表 / 红黑树,匹配 key(hash 相等且 equals 为 true)。
3. V remove(Object key)
  • 功能:删除指定 key 的键值对,返回被删除的 value(无则返回 null)。
  • 底层逻辑
    • 定位 key 所在节点,删除后若为红黑树且节点数少于 6,会退化为链表;若为链表则直接调整指针。
4. boolean containsKey(Object key)
  • 功能:判断是否包含指定 key。
  • 逻辑:类似 get,找到匹配的 key 则返回 true。
5. boolean containsValue(Object value)
  • 功能:判断是否包含指定 value。
  • 逻辑:遍历整个哈希表(数组 + 链表 / 红黑树),逐个比较 value(效率低,时间复杂度 O (n))。

2、批量操作方法

1. void putAll(Map<? extends K, ? extends V> m)
  • 功能:将另一个 Map 中的所有键值对插入当前 HashMap。
  • 逻辑:遍历参数 Map,逐个调用 put 方法。
2. void clear()
  • 功能:清空所有键值对。
  • 逻辑:遍历数组,将所有节点置为 null,size 设为 0(不缩容,数组长度不变)。

3、集合视图方法(返回视图,而非拷贝)

1. Set<K> keySet()
  • 功能:返回所有 key 的集合视图(Set)。
  • 特性:视图的修改会同步到原 HashMap(如 keySet().remove(key) 会删除原 Map 中的键值对)。
2. Collection<V> values()
  • 功能:返回所有 value 的集合视图(Collection)。
  • 特性:同上,修改会同步到原 Map。
3. Set<Map.Entry<K, V>> entrySet()
  • 功能:返回所有键值对(Entry)的集合视图(Set)。
  • 用途:高效遍历(for (Entry<K,V> entry : map.entrySet())),可通过 entry.setValue(value) 修改 value。

4、容量与大小相关方法

1. int size()
  • 功能:返回当前键值对数量。
2. boolean isEmpty()
  • 功能:判断是否为空(size() == 0)。
3. int capacity()(JDK 1.8+ 新增,默认包访问权限)
  • 功能:返回当前数组容量(table.length),外部无法直接调用,需通过反射获取。
4. float loadFactor()
  • 功能:返回负载因子(默认 0.75),用于计算扩容阈值(threshold = capacity * loadFactor)。

5、其他重要方法

1. void resize()(核心内部方法)
  • 功能:数组扩容(默认翻倍),重新计算所有节点的索引并迁移,是 put 方法中保证性能的关键。
  • 触发时机size 超过阈值时。
2. final int hash(Object key)(内部方法)
  • 功能:计算 key 的哈希值,通过高 16 位与低 16 位异或((h = key.hashCode()) ^ (h >>> 16))减少哈希冲突。
3. Object clone()
  • 功能:返回浅拷贝(键值对本身是新对象,但 key 和 value 仍为原引用)。

关键特性总结

  • 线程不安全:多线程并发修改(如 put 和 resize 同时进行)可能导致数据异常(如链表环化)。
  • 无序性:迭代顺序与插入顺序无关(JDK 1.8 中红黑树可能影响顺序),需有序性可使用 LinkedHashMap
  • 性能:理想情况下 put/get 时间复杂度为 O (1),哈希冲突严重时退化至 O (n)(链表)或 O (log n)(红黑树)。

三、哈希冲突

哈希冲突(Hash Collision)是哈希表(如 HashMap)中常见的现象,指不同的键(key)经过哈希函数计算后得到相同的哈希值,导致它们需要存储在哈希表的同一位置。理解哈希冲突的产生原因、解决方法及影响,对设计和使用哈希表至关重要。

1、为什么会产生哈希冲突?

哈希表的核心是通过哈希函数将键映射到数组的索引位置(index = hash(key) % 数组长度)。由于:

  1. 键的范围远大于数组长度:例如,字符串、对象等键的可能取值是无限的,而哈希表数组长度是有限的(即使动态扩容,也不可能覆盖所有可能的键)。
  2. 哈希函数的局限性:任何哈希函数都无法完全避免不同的键映射到同一索引(数学上 “鸽巢原理”:n 个鸽子放进 m 个鸽巢,n > m 时必然有鸽巢包含多个鸽子)。

因此,哈希冲突是不可避免的,只能通过优化减少冲突概率或高效处理冲突。

2、解决哈希冲突的常见方法

哈希表通过特定机制处理冲突,确保即使哈希值相同,键值对也能正确存储和查找。主流方法有两种:

1. 链地址法(Chaining)
  • 原理:哈希表数组的每个位置(桶,Bucket)不仅存储单个键值对,还存储一个链表(或红黑树),所有哈希冲突的键值对都按顺序存入该链表 / 树中。
  • 流程
    • 当新键值对的哈希值对应索引已存在数据时,直接将其添加到该位置的链表尾部(或红黑树中)。
    • 查询时,先通过哈希值定位到索引,再遍历链表 / 树匹配 key。
  • 优点
    • 处理简单,不易产生聚集效应(一个冲突不会影响其他位置)。
    • 动态扩容时迁移数据方便。
  • 应用:Java 的 HashMap(JDK 1.8 中,当链表长度 > 8 时转为红黑树,提升查询效率)、Python 的 dict 等。
2. 开放地址法(Open Addressing)
  • 原理:当哈希冲突发生时,通过某种规则(探查序列)在数组中寻找下一个空闲位置存储键值对,而不是使用链表。
  • 常见探查方式
    • 线性探查:冲突时依次检查下一个位置(index+1, index+2, ...),直到找到空闲位置。
    • 二次探查:冲突时按平方数偏移(index+1², index-1², index+2², ...),减少聚集效应。
    • 双重哈希:使用第二个哈希函数计算偏移量,降低探查序列的规律性。
  • 优点:数据存储在数组中,访问速度快(无需遍历链表)。
  • 缺点
    • 容易产生 “聚集效应”(连续多个位置被占用,导致新插入的键需要探查更远的位置)。
    • 删除数据复杂(不能直接置空,否则会断裂探查序列,需标记为 “已删除”)。
  • 应用:Java 的 ThreadLocal(底层 ThreadLocalMap 使用开放地址法)、某些数据库索引。

3、如何减少哈希冲突的概率?

虽然冲突不可避免,但可通过以下方式降低冲突频率:

  1. 优化哈希函数
    • 让哈希值分布更均匀,减少 “热点索引”(某一位置聚集大量键值对)。例如,JDK 1.8 中 HashMap 的哈希函数通过 (h = key.hashCode()) ^ (h >>> 16) 将高 16 位与低 16 位异或,增强随机性。
  2. 合理设置哈希表容量
    • 容量通常设为 2 的幂(如 HashMap 初始容量 16),配合 index = (n-1) & hash 计算索引,确保哈希值的低位能均匀分布到数组中。
  3. 动态扩容
    • 当哈希表中键值对数量(size)超过阈值(容量 × 负载因子,默认 0.75)时,触发扩容(容量翻倍),降低负载,减少冲突。

4、哈希冲突对性能的影响

  • 链地址法:若冲突较少,链表 / 红黑树的查询时间接近 O (1);若冲突严重(如哈希函数设计差),链表会过长,查询时间退化至 O (n)(红黑树可优化至 O (log n))。
  • 开放地址法:冲突越多,探查次数越多,插入和查询效率越低,极端情况下可能接近 O (n)。

因此,良好的哈希函数设计和扩容策略是保证哈希表高性能的关键。

总结

哈希冲突是哈希表的固有问题,核心解决思路是链地址法(主流)和开放地址法。实际开发中,我们无需手动处理冲突(如 HashMap 已封装实现),但理解其原理有助于更好地使用哈希表(如避免使用哈希值分布差的 key,合理设置初始容量等)。


MySQL优化
RBAC在项目里的应用
SPI 类加载
双亲委托机制以及为什么要用
JVM

  • 栈和堆的异常了解哪些
  • 内存溢出是怎么导致的
  • CPU飙升一般是什么导致的
  • fullGC

线程池的几个参数
SQL执行计划
事务隔离级别,你平时常用哪个级别
连接大量字符串一般是怎么做的
单例模式
泛型了解多少
基础类型可以用泛型吗为什么
泛型擦除
深拷贝浅拷贝

1.MySQL优化

  • 索引优化
    • 为查询频繁的字段(where、join、order by)建索引,避免索引失效(如模糊查询 % 开头、函数操作索引列、类型隐式转换)。
    • 控制索引数量(过多会拖慢写入),优先用联合索引(遵循最左前缀原则)。
  • SQL 优化
    • 避免 select *,只查需要的字段;避免子查询,改用 join;分页优化(limit 大偏移量时用索引定位)。
    • 禁止在 where 子句中使用!=、not in、or,可能导致全表扫描。
  • 表结构优化
    • 选择合适字段类型(如用 int 代替 varchar 存手机号),避免大字段(text/blob),必要时分表(水平 / 垂直分表)。
  • 配置优化
    • 调整连接池参数(max_connections)、缓存大小(innodb_buffer_pool_size)、日志刷盘策略(innodb_flush_log_at_trx_commit)。

2.RBAC在项目里的应用

RBAC(基于角色的访问控制)是权限管理的主流模型,核心是 “用户 - 角色 - 权限” 三层关系:

  • 用户:系统操作者(如 admin、user1)。
  • 角色:一组权限的集合(如管理员、普通用户),用户可关联多个角色。
  • 权限:具体操作(如查询、删除)或资源(如菜单、接口)。
  • 应用场景
    • 数据库设计:通常需 5 张表(用户表、角色表、权限表、用户 - 角色关联表、角色 - 权限关联表)。
    • 实现逻辑:用户登录后,查询其关联的角色→获取角色对应的权限→校验接口 / 按钮权限(如 Spring Security 结合 RBAC)。

3. SPI 类加载

  • 定义:Java 提供的一种服务发现机制,允许第三方为接口提供实现,无需硬编码依赖。
  • 流程
    1. 定义接口(如com.example.Plugin)。
    2. 第三方实现接口(如com.example.impl.PluginImpl)。
    3. META-INF/services/下创建以接口全类名为名的文件,内容为实现类全类名。
    4. 程序通过ServiceLoader.load(Plugin.class)加载所有实现类。
  • 应用:JDBC 驱动加载(java.sql.Driver)、日志框架适配、Spring 的 SPI 扩展(如SpringFactoriesLoader)。

4.双亲委托机制以及为什么要用

  • 类加载过程:加载(读 class 文件到内存)→验证(校验字节码合法性)→准备(静态变量赋默认值)→解析(符号引用转直接引用)→初始化(执行静态代码块、赋初始值)。
  • 双亲委托机制
    • 类加载器加载类时,先委托给父加载器,父加载器无法加载时才自己加载。
    • 加载器层级:Bootstrap(核心类,如 java.lang.String)→Extension→Application→自定义加载器。
  • 为什么用
    1. 避免类重复加载(如java.lang.String不会被自定义加载器篡改)。
    2. 保证核心类的安全性(防止恶意替换核心类)。

5.JVM

  • 栈和堆的异常
    • 栈异常
      • StackOverflowError:栈深度超过虚拟机限制(如递归调用无终止条件)。
      • OutOfMemoryError: StackOverflowError:栈动态扩展时内存不足(极少发生,通常与线程数过多有关)。
    • 堆异常
      • OutOfMemoryError: Java heap space:堆内存不足(对象过多未回收,如内存泄漏)。
  • 内存溢出(OOM)原因
    • 堆:创建大量对象且长期被引用(如静态集合缓存未清理)。
    • 方法区(元空间):加载类过多(如动态生成大量类,CGLib 代理滥用)。
    • 直接内存:NIO 的 DirectByteBuffer 分配过大,且未释放。
  • CPU 飙升原因
    • 死循环(如代码逻辑错误导致无限循环)。
    • 频繁 GC(对象创建 / 回收过于频繁,导致 GC 线程占用大量 CPU)。
    • 锁竞争激烈(大量线程争夺同一把锁,导致上下文切换频繁)。
  • Full GC
    • 触发:老年代空间不足、元空间不足、调用System.gc()(仅建议,不保证执行)。
    • 影响:STW(Stop The World)时间长,频繁 Full GC 会导致应用卡顿,需优化(如减少大对象创建、调整老年代大小)。

6.线程池的几个参数

ThreadPoolExecutor的核心参数:

  1. corePoolSize:核心线程数(长期存活,即使空闲也不销毁)。
  2. maximumPoolSize:最大线程数(核心线程 + 临时线程的上限)。
  3. keepAliveTime:临时线程空闲超时时间(超过则销毁)。
  4. workQueue:任务等待队列(核心线程满时,新任务入队)。
  5. threadFactory:线程创建工厂(自定义线程名、优先级等)。
  6. handler:拒绝策略(队列满且线程达最大值时,处理新任务的方式,如 AbortPolicy 直接抛异常)。

7.SQL执行计划

通过EXPLAIN + SQL语句查看,关键字段:

  • type:访问类型(性能从优到差:system > const > eq_ref > ref > range > index > ALL),目标是达到range或更好。
  • key:实际使用的索引(为 NULL 则未用索引)。
  • rows:预估扫描行数(越小越好)。
  • extra:额外信息(如Using index表示覆盖索引,Using filesort表示文件排序,需优化)。

8.事务隔离级别(常用)

MySQL 默认是可重复读(Repeatable Read),日常开发中最常用:

  • 避免脏读(读未提交数据)和不可重复读(同一事务内多次读结果不一致)。
  • 多数业务(如订单、支付)只需保证这两点,串行化(Serializable)性能太差,读已提交(Read Committed)可能有不可重复读问题。

9.连接大量字符串的做法

保证一个类只有一个实例,常用实现:

  • 饿汉式:类加载时初始化(线程安全,可能浪费内存)。
  • 懒汉式(双重校验锁):延迟初始化,加锁保证线程安全(volatile防止指令重排)。
public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

11. 泛型

  • 定义:参数化类型,编译时检查类型安全,避免强制转换(如List<String>只能存字符串)。
  • 基础类型不能用泛型:泛型擦除后会转为 Object,而基础类型(int、char 等)不是 Object 子类,需用包装类(Integer、Character)。
  • 泛型擦除:编译后泛型信息被擦除(如List<String>变为List),目的是兼容 JDK1.5 之前的版本,可能导致运行时类型转换问题(需用Class.cast()处理)。

12. 深拷贝 & 浅拷贝

  • 浅拷贝:复制对象时,仅复制基本类型字段,引用类型字段仍指向原对象(如Object.clone()默认浅拷贝)。
  • 深拷贝:复制对象及所有引用类型字段(递归拷贝),两者完全独立。
  • 实现
    • 浅拷贝:实现Cloneable接口,重写clone()
    • 深拷贝:序列化(对象及引用对象都实现Serializable)、递归调用clone()

http://www.dtcms.com/a/519526.html

相关文章:

  • 如何提高技能和知识
  • 小白python入门 - 6. Python 分支结构——逻辑决策的核心机制
  • 证件阅读器在酒店案例
  • 免费做app的网站有哪些物流公司网站怎么做
  • 公司网站制作商濮阳到上海
  • 网络编程-初识
  • 十六、OpenCV中的图像文件处理
  • 你的图表太安静了!3行代码让Highcharts“开口说话“
  • 网站地图制作工具抽卡 wordpress
  • digiCamControl,一款专业级 DSLR 远程控制工具
  • 成功解决NVIDIA Jetson docker环境下Opencv+Gstreamer 无法对rtsp相机拉流问题
  • 2025年保姆级C++环境配置教程(Windows/macOS双平台)
  • Linux内核中RDMA资源的精细化管理:cgroup子系统实现解析
  • Rust 性能优化指南:内存管理、并发调优与基准测试案例
  • 手机免费注册网站网站的根目录怎么找
  • 贯通 “车 - 网 - 储” 关键节点,推动新能源汽车与能源网融合助力 “双碳” 目标
  • 计网4.2.5 路由聚合
  • 基于PRIDE PPP-AR的低轨卫星运动学定轨脚本
  • 【Rust实战】打造高性能命令行工具:从grep到ripgrep的进化之路
  • 2510rs,rust,1.89
  • 移动归因平台对比:洞察AppsFlyer、Adjust与Singular的胜负手
  • 2510rs,rust,1.88
  • 网站的文案电商关键字优化
  • 网站如何屏蔽中国ip如何看网站做打好坏
  • Linux1023 mysql 修改密码等
  • Arbess从入门到实战(16) - 使用Arbess+Gitee实现K8s自动化部署
  • 《剖析 Linux 文件系统:架构、原理与实战操作指南》
  • 最新彩虹云商城系统源码 V7.2 全解版本无后门 含搭建教程19套模版
  • 【Linux】Ext系列文件系统 从磁盘结构到文件存储的原理剖析
  • 关系数据库2.3-2.4