面经来源于牛客:https://www.nowcoder.com/share/jump/1686814541955
答案解析
1.自我介绍
在自我介绍时需要讲清楚以下 4 点:
- 你是谁?
- 你会什么技能?
- 使用这些技能做出过什么项目或成绩?(如果有编程大赛的经历更好)
- 你的优势是啥?为什么我们要用你?(可以讲解你的技术栈和企业技术栈的比较匹配)
2.Map 接口实现
Map 是接口,本身没有任何实现,但它的实现类有 HashMap、LinkedHashMap 和 TreeMap 等。 其中,HashMap 是最常见的实现类之一,它的底层在 JDK 1.8 时,是使用数组 + 链表或红黑树的结构来实现的,在 JDK 1.8 之前,它使用的是数组 + 链表来实现的 。
3.HashMap 和 LinkedHashMap 有什么区别?
HashMap 和 LinkedHashMap 都是 Map 接口的实现,并且都是非线程安全的容器,它们的区别有以下两点:
- 迭代顺序:
- HashMap:HashMap 不保证迭代顺序,即元素的遍历顺序是不确定的。它是通过哈希值进行快速查找的,而不考虑元素的插入顺序。
- LinkedHashMap:LinkedHashMap 继承自 HashMap,它保留了元素的插入顺序。迭代 LinkedHashMap 时,元素按照插入的顺序进行访问。
- 性能:
- HashMap:HashMap 在插入和查找操作上具有很好的性能,因为它使用了哈希表的快速查找特性。它的时间复杂度为 O(1)。
- LinkedHashMap:由于 LinkedHashMap 需要维护插入顺序,所以在插入和删除操作上相对于 HashMap 要稍慢一些。但是,其性能仍然很好,并且与 HashMap 相比差异不大。
4.MySQL 索引失效的场景有哪些?
导致索引失效的场景有以下这些:
- 未遵循最左匹配原则
- 使用列运算
- 使用函数方法
- 类型转换
- 使用 is not null
- 错误的模糊匹配,使用右 % 开始查询。
具体详情,参考:https://www.javacn.site/interview/mysql/indexinvalid.html
5.Redis 数据结构
Redis 常用的数据类型有 5 种:String 字符串类型、List 列表类型、Hash 哈希表类型、Set 集合类型、Sorted Set 有序集合类型,如下图所示: 这 5 种常用类型的用途如下:
- String(字符串类型)常见使用场景是:存储 Session 信息、存储缓存信息(如详情页的缓存)、存储整数信息,可使用 incr 实现整数+1,和使用 decr 实现整数 -1;
- List(列表类型)常见使用场景是:实现简单的消息队列、存储某项列表数据;
- Hash(哈希表类型)常见使用场景是:存储 Session 信息、存储商品的购物车,购物车非常适合用哈希字典表示,使用人员唯一编号作为字典的 key,value 值可以存储商品的 id 和数量等信息、存储详情页信息;
- Set(集合类型)是一个无序并唯一的键值集合,它的常见使用场景是:关注功能,比如关注我的人和我关注的人,使用集合存储,可以保证人员不会重复;
- Sorted Set(有序集合类型)相比于 Set 集合类型多了一个排序属性 score(分值),它的常见使用场景是:可以用来存储排名信息、关注列表功能,这样就可以根据关注实现排序展示了。
6.Redis 缓存击穿
缓存击穿是指在缓存系统中,某个热点数据过期或失效时,同时有大量的请求访问该数据,导致请求直接访问数据库或后端服务,给数据库或后端服务造成巨大压力,导致系统性能下降甚至崩溃的现象。 缓存击穿可能发生的原因包括:
- 热点数据失效:当某个热点数据过期时,此时大量请求访问该数据,导致缓存失效,请求直接访问数据库。
- 并发访问热点数据:在高并发环境下,大量的请求同时访问同一个热点数据,导致该热点数据在缓存失效期间被并发地访问,触发缓存击穿。
为了解决缓存击穿问题,可以采取以下策略:
- 设置热点数据永不过期或过期时间较长:对于一些热点数据,可以将其设置为永不过期,或者设置一个较长的过期时间,确保热点数据在缓存中可用,减少因为过期而触发的缓存击穿。
- 加互斥锁或分布式锁:在访问热点数据时,可以引入互斥锁或分布式锁,保证只有一个线程去访问后端服务或数据库,其他线程等待结果。当第一个线程获取到数据后,其他线程可以直接从缓存获取,避免多个线程同时访问后端服务,减轻压力。
- 限制并发访问:通过限制并发访问热点数据的请求量,可以控制请求的流量,避免过多请求同时访问热点数据。
7.Spring Boot 常用注解
Spring Boot 中的常用注解有很多,比如以下这些:
- @SpringBootApplication:标记一个主要的 Spring Boot 应用的启动类。
- @Controller:将类标记为控制器,处理 HTTP 请求。
- @RestController:类似于 @Controller,但是它还将返回的对象自动转换为 JSON 格式。
- @RequestMapping:用于映射 HTTP 请求到具体的处理方法。
- @GetMapping、@PostMapping、@PutMapping、@DeleteMapping:用于分别处理 GET、POST、PUT、DELETE 请求。
- @RequestParam:用于将请求参数绑定到处理方法的参数上。
- @PathVariable:用于将 URL 路径变量绑定到处理方法的参数上。
- @RequestBody:用于将请求体绑定到处理方法的参数上。
- @Autowired:用于自动装配依赖关系,通过类型进行依赖注入。
- @Qualifier:与 @Autowired 一起使用,指定注入的具体实现。
- @Value:用于注入配置属性值。
- @Component:将类标记为 Spring 容器的组件。
- @Service:将类标记为服务层组件。
- @Repository:将类标记为数据访问层组件。
- @Configuration:标记类为配置类,用于定义配置项。
- @Bean:在配置类中使用,用于声明一个 Bean 对象。
8.#{} 和 ${} 的区别?
${} 和 #{} 在 MyBatis 中都是用于 SQL 参数替换的符号,它们的区别主要体现在以下几个方面:
- 功能不同:${} 是直接替换,而 #{} 是预处理;
- 使用场景不同:普通参数使用 #{},如果传递的是 SQL 命令或 SQL 关键字,需要使用 ${},但在使用前一定要做好安全验证;
- 安全性不同:使用 ${} 存在安全问题,如 SQL 注入,而 #{} 则不存在安全问题。
9.MyBatis 如何分页?
MyBatis 实现分页有两种常见的方式:
- 手写 SQL 进行分页:比如 MySQL 中使用 limit x offset y 即可实现分页,分页的公式是 (pageIndex-1)*pageSize;
- 使用分页插件 PageHelper:PageHelper 是一个开源的分页插件,基于拦截器实现。它通过拦截 Executor 的 query 方法,在执行查询前拦截并修改 SQL 语句,实现分页逻辑的。
10.TCP 和 UDP 有什么区别?
TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议) 都是传输层的重要协议,它们都是用来将数据从源主机发送到目标主机的,但它们存在以下几点不同:
- 连接机制不同:TCP 是面向连接的协议,需要在客户端和服务器之间建立一个稳定的连接,然后再进行数据传输;而 UDP 是无连接的协议,数据包可以直接发送给目标主机,不需要事先建立连接。
- 数据传输方式不同:TCP 采用可靠的数据传输方式,即在传输过程中使用序号、确认号和重传机制等控制手段来保证数据的可靠传输;而 UDP 采用不可靠的数据传输方式,数据包可能会丢失或重复,不提供数据可靠性保障。
- 数据传输效率不同:由于 TCP 需要进行连接、序号确认等额外的数据包传输,因此在数据传输效率方面相对于 UDP 要低一些。
- 数据大小限制不同:TCP 对数据包的大小有限制,最大只能传输 64KB 的数据,而 UDP 的数据包大小没有限制。
- 应用场景不同:TCP 适用于要求数据传输可靠性高的场景,如网页浏览、文件下载、电子邮件等;而 UDP 适用于实时性要求较高的场景,如视频会议、在线游戏等。
具体细节请访问:https://www.javacn.site/interview/net/tcpvsudp.html
小结
小厂的面试题总体来说不难,都是常见的基础题,在扎实的掌握了 Java 技术之后,这些问题应该都能轻松拿下。
以上内容来自我的 《Java 面试突击训练营》,这门课程是 有着 14 年工作经验(前 360 开发工程师),9 年面试官经验的我,花费 4 年时间打磨完成的一门视频面试课。
整个课程从 Java 基础到微服务 Spring Cloud、从实际开发问题到场景题应有尽有,如下图所示:
全程通过视频直播 + 录播的方式,把 Java 常见的面试题系统的过一遍,遇到一个问题,把这个问题相关的内容都给大家讲明白,并且视频支持永久更新和观看。
上完训练营的课程之后,基本可以应对目前市面上绝大部分公司的面试了,想要了解详情,加我微信:vipStone【备注:训练营】