《互联网大厂Java求职者面试:核心知识大考验》

29 阅读4分钟

面试官:第一轮面试开始,首先问你,Java 中 HashMap 的底层数据结构是什么?

王铁牛:嗯……是数组加链表吧。

面试官:回答正确。那当链表长度达到多少时会转化为红黑树?

王铁牛:这个我知道,是8。

面试官:不错。再问你,HashMap 在多线程环境下会出现什么问题?

王铁牛:会出现数据丢失、死循环这些问题。

面试官:好,第一轮面试表现还不错。接下来第二轮面试。说说 ArrayList 的扩容机制。

王铁牛:它每次扩容是原来容量的1.5倍。

面试官:对。那如果我不断往一个初始容量为10的 ArrayList 里添加元素,它具体的扩容过程是怎样的?

王铁牛:呃……就是容量到了10之后,变成15,然后到了15之后变成22这样。

面试官:回答得不太准确。最后一个问题,ArrayList 是线程安全的吗?

王铁牛:不是。

面试官:好,第二轮面试结束。现在进入第三轮面试。Spring 框架的核心特性有哪些?

王铁牛:有依赖注入、面向切面编程这些。

面试官:嗯。那 Spring Boot 自动配置原理是什么?

王铁牛:这个……不太清楚。

面试官:最后一个问题,MyBatis 的缓存机制了解吗?

王铁牛:就一级缓存和二级缓存吧。

面试官:好,面试结束。回家等通知吧。

答案:

  1. HashMap 底层数据结构:HashMap 底层是数组加链表(在 JDK 1.8 之后链表长度大于 8 且数组长度大于 64 时会转化为红黑树)。数组是 HashMap 的基础结构,每个元素是一个 Node 节点,包含键值对等信息。链表用于解决哈希冲突,当多个键值对哈希到同一个位置时,就会在该位置形成链表。红黑树则是为了提高链表过长时的查询效率。
  2. HashMap 在多线程环境下的问题:在多线程环境下,HashMap 可能会出现数据丢失和死循环问题。例如在扩容时,如果多个线程同时操作,可能会导致链表形成环形结构,进而造成死循环。同时,在并发写操作时,可能会覆盖其他线程写入的数据,导致数据丢失。
  3. ArrayList 扩容机制:ArrayList 初始容量为 10。当添加元素导致容量不足时,会进行扩容。扩容时新容量是原来容量的 1.5 倍。例如初始容量为 10,第一次扩容后变为 15,第二次扩容后变为 22(15 * 1.5 = 22.5,取整为 22)。扩容过程会创建一个新的更大容量的数组,然后将原数组的元素复制到新数组中。
  4. Spring 框架的核心特性:依赖注入(DI),通过控制反转(IoC)容器将对象之间的依赖关系注入到对象中;面向切面编程(AOP),可以在不修改业务逻辑的前提下,对横切关注点进行模块化处理,比如日志记录、事务管理等;IoC 容器管理对象的创建、生命周期和依赖关系;支持基于 XML、注解等多种配置方式;提供事务管理功能,方便进行数据库事务操作;提供面向切面的编程支持,用于实现诸如日志记录、性能监测等功能;支持各种 Web 框架,如 Spring MVC 用于构建 Web 应用。
  5. Spring Boot 自动配置原理:Spring Boot 自动配置是基于 Spring 的条件化配置实现的。它通过大量的 @Conditional 注解来判断当前环境是否满足配置条件。例如,如果项目中引入了 MySQL 依赖,并且在类路径下能找到相关的数据库驱动,那么就会自动配置数据源等相关组件。Spring Boot 会扫描 classpath 下的 META - INF/spring.factories 文件,其中定义了各种自动配置类。这些自动配置类会根据条件进行加载和配置,将符合条件的组件注册到 Spring 容器中,从而实现自动配置。
  6. MyBatis 缓存机制:MyBatis 有一级缓存和二级缓存。一级缓存是 SqlSession 级别的缓存,当在同一个 SqlSession 中执行相同的 SQL 语句时,会直接从一级缓存中获取数据,不会再次查询数据库。一级缓存的作用域是同一个 SqlSession,当 SqlSession 关闭时,一级缓存也会被清空。二级缓存是基于 namespace 级别的缓存,多个 SqlSession 可以共享二级缓存。开启二级缓存后,当不同的 SqlSession 执行相同的 SQL 语句时,会先从二级缓存中查询数据。二级缓存的实现依赖于 Cache 接口,MyBatis 提供了多种缓存实现,如 PerpetualCache 等。