一、集合


数组

ArrayList 和 LinkedList 的区别?

ArrayList 底层是数组结构,可以通过下标直接访问元素,因此查询效率较高;但在中间插入或删除元素时,可能需要移动后续元素,效率相对较低。

LinkedList 底层是双向链表结构,查询时需要从头节点或尾节点遍历,效率较低;但插入或删除元素时只需修改前后节点指针,效率较高。

因此在查询较多的场景下通常使用 ArrayList,而在频繁插入删除的场景下可以考虑使用 LinkedList。

详细可参阅:
ArrayList和LinkedList的区别?


为什么实际开发中我们几乎都用 ArrayList?

实际开发中更多使用 ArrayList,主要有三个原因:

第一,大多数业务场景是查询多、插入删除少;
第二,LinkedList 每个节点都需要额外存储前后指针,占用更多内存空间;
第三,ArrayList 基于连续内存存储,对 CPU 缓存更加友好,整体性能更优。

需要注意的是,LinkedList 虽然插入删除理论上快,但前提是已经定位到节点,而定位过程仍然需要遍历。


HashMap

HashMap 是一个用于存储键值对(key-value)的集合,线程不安全。

详解:
深入理解 HashMap的数据结构


底层架构是什么?

在 JDK1.8 中,HashMap 的底层结构是:

数组 + 链表 + 红黑树

工作流程:

  • 通过 key 的 hash 计算数组下标

  • 如果没有冲突,直接存储

  • 如果发生冲突,使用链表解决

  • 当链表长度超过 8 时,会转换为红黑树,提高查询效率

红黑树是一种自平衡的二叉查找树,能够保证查询效率。


为什么 HashMap 的容量一定是 2 的幂?

HashMap 的容量设计为 2 的幂,是为了让:

hash % length

可以通过:

hash & (length - 1)

代替,从而提高计算数组下标的效率。


二、多线程


进程和线程的区别

进程是操作系统分配资源的基本单位,每个进程都有独立的内存空间;

线程是 CPU 调度的基本单位,一个进程可以包含多个线程;

同一进程内的线程共享内存和资源,因此线程创建和切换开销较小,但也更容易出现线程安全问题。


为什么线程切换比进程切换快?

进程切换需要保存和恢复整个内存空间,而线程切换只需要切换执行上下文,因此开销更小。


线程之间为什么会有线程安全问题?

因为多个线程共享同一块内存,当多个线程同时修改同一变量时,可能会导致数据不一致的问题。

线程安全问题的本质是:多个线程同时访问共享资源。


线程的生命周期和状态?

五种周期:新建、就绪、运行、阻塞、销毁

6 种状态(NEWRUNNABLEBLOCKEDWAITINGTIME_WAITINGTERMINATED


并发和并行的区别

并发是指多个任务在同一时间段内交替执行,看起来像同时发生;

并行是指多个任务在同一时刻真正同时执行,通常需要多核 CPU 支持。


Java 是并发还是并行?

Java 支持并发;在多核 CPU 环境下可以实现并行。


synchronized 的作用

synchronized 是 Java 提供的关键字,用于保证多线程环境下的线程安全。

它可以对方法或代码块加锁,保证同一时间只有一个线程可以执行,从而避免数据不一致问题。

补充说明:

  • 属于悲观锁

  • 是可重入锁

  • 基于对象锁实现


什么是死锁?

死锁是指多个线程(或进程)互相持有对方需要的资源,彼此等待,导致程序无法继续执行的情况。


死锁产生的四个必要条件

  • 互斥

  • 请求与保持

  • 不可剥夺

  • 循环等待

如果记不住四个条件,记住“资源互相等待”即可。


如何避免死锁?

可以通过统一加锁顺序来避免死锁,例如规定所有线程必须按照相同顺序获取锁。


String、StringBuilder、StringBuffer

String 是不可变字符串,线程安全。

StringBuilder 是可变字符串,线程不安全,但性能较高。

StringBuffer 是可变字符串,线程安全,但性能略低。

在实际开发中,一般使用 StringBuilder。


三、MySQL

何为索引?有什么作用?

索引是数据库中用于提高查询效率的一种数据结构,本质上是一种有序的数据结构,用来加快数据的查找速度。

索引的主要作用是:

  1. 提高查询效率
  2. 加快排序和分组操作
  3. 减少磁盘 IO 次数

缺点是占用额外存储空间,增删改会变慢(因为要维护索引)


MySQL 索引底层是什么?

InnoDB 存储引擎使用 B+ 树作为索引结构。

为什么用 B+树,不用红黑树?

因为 B+树适合磁盘存储,能减少磁盘 IO 次数,适合范围查询。


主键索引和普通索引区别?

主键索引是唯一索引,不允许重复;普通索引允许重复。

更专业的回答是:InnoDB 的主键索引是聚簇索引^1,数据和索引存储在一起;普通索引是二级索引。


四、Redis


Redis 为什么这么快?

Redis 快的原因主要有三个:

第一,基于内存存储,避免磁盘 IO;
第二,采用单线程模型,避免线程切换开销;
第三,使用 IO 多路复用机制,提高网络处理效率。


为什么 Redis 用单线程还那么快?

因为 Redis 是基于内存操作,避免了磁盘 IO,并且单线程避免了线程切换的开销,同时通过 IO 多路复用处理高并发请求。


Redis 常用数据类型

String
Hash
List
Set
ZSet

说一说hash类型的底层数据结构

Redis的哈希对象的底层存储可以使用ziplist(压缩列表)和hashtable(字典)。

当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认512个),同时所有值都小于hash-max-ziplist-value配置(默认64 字节)时,Redis会使用ziplist作为哈希的内部实现。ziplist使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而 hashtable的读写时间复杂度为O(1)。


MySQL 和 Redis 的区别

Redis 是基于内存的 Key-Value 数据库,读写速度非常快,通常用于缓存、会话存储、排行榜等高频访问场景;

MySQL 是关系型数据库,主要用于持久化存储结构化数据,支持事务和复杂 SQL 查询。


为什么要用 Redis 做缓存?

使用 Redis 做缓存主要是为了提高系统响应速度,并减轻 MySQL 的访问压力。

由于 Redis 基于内存存储,读写性能非常高,可以将高频访问的数据放入缓存,从而减少数据库查询次数,提高系统整体性能。


常见的HTTP协议请求头有哪些?