面灵AI→

招银网络科技一面面经:Java 集合、Spring 注入与流式 AI 接口设计

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

一、自我介绍与经历

  1. 请做一个自我介绍,大概两到三分钟

二、Java 基础

  1. 介绍一下 Java 的集合类,它下面都有哪些实现,在什么场景下使用,区别是什么?
  2. Set 和 List 有什么区别?
  3. HashMap 是一个什么样的结构?说底层一点
  4. 在代码里 new 一个 HashMap,它默认的长度是多少?
  5. 它什么时候会扩容?介绍一下扩容机制
  6. 它扩容扩多少?
  7. Java 里线程创建方式有哪些?
  8. Runnable 和 Callable 有什么区别?
  9. 起线程要调用 start 方法,如果直接调用 run 方法会怎么样?

三、Spring 框架

  1. 接口的异常是怎么处理的?接口要对入参做校验,参数有问题时怎么做异常处理、返回什么响应体?
  2. 业务逻辑处理时,比如数据库理论上应该返回一条记录但一条也没返回,这种异常怎么处理、返回什么响应体?
  3. Spring 里 @Autowired 和 @Resource 的区别是什么?
  4. 一个接口 Animal 有两个实现 Dog 和 Cat,现在想在一个方法里注入 Dog,怎么注入?

四、数据库

  1. MySQL 建一个联合索引 ABC,查询条件是 A 等于什么 and C 等于什么,这种情况是什么?哪些前缀能走索引?
  2. 除了刚刚说的,还有哪些索引失效的情况?

五、AI 场景与系统设计

  1. 现在 AI 用得比较多,我希望做一个跟 AI 对话的后端接口并且是流式输出的,像豆包那样几个字几个字蹦出来,该选哪种通信方式、怎么实现?
  2. 你是用 POST 还是 GET 的接口?
  3. POST 接口用 SSE 实现流式返回,跟普通 POST 接口还有什么区别?比如请求头上有哪些不一样的地方?

六、项目与实习

  1. 找一个你比较熟悉的项目交流一下:你在这个项目中主要负责哪一部分?有没有遇到技术难点或比较复杂的技术挑战,是怎么解决的?
  2. 这个项目有做测试吗?怎么测的?

七、算法与编码

  1. 编程题:合并区间

《参考解析》

  1. HashMap 的底层与扩容要能一路答到底:JDK 8 起是数组 + 链表 + 红黑树,链表长度到 8 且数组容量到 64 才树化。new HashMap() 默认不分配数组,第一次 put 时才初始化为 16;默认负载因子 0.75,元素数超过「容量 × 0.75」就扩容,扩容是翻倍(左移一位)。扩容时要重新分布元素:JDK 8 用高位与运算判断索引是否变化,避免重新计算 hash。追问常落在「为什么是 0.75」(时间与空间的折中)、「为什么容量是 2 的幂」(用位运算代替取模)、以及「多线程扩容为什么会成环」。

  2. 集合类这题要按接口层次讲:顶层 Collection 分 List、Set、Queue 三条线,Map 单独一支。List 有序可重复(ArrayList 数组、LinkedList 链表、CopyOnWriteArrayList 读多写少并发);Set 去重(HashSet 基于 HashMap、TreeSet 有序、LinkedHashSet 保插入序);Map 存键值对(HashMap 无序、LinkedHashMap 保序可做 LRU、TreeMap 按 key 排序、ConcurrentHashMap 并发)。选型口径是「要不要顺序、要不要去重、是否并发」,把这三点讲清就不散。

  3. @Autowired 与 @Resource 的区别:来源不同(前者是 Spring 注解,后者是 JSR-250 规范);注入方式不同——@Autowired 默认按类型注入,同类型多个实现时要用 @Qualifier 指定名字或配合 @Primary,而 @Resource 默认按名字注入、找不到名字再退回类型。所以「Animal 有 Dog 和 Cat 两个实现,怎么注入 Dog」的标准答案是 @Resource(name = "dog") 或 @Autowired @Qualifier("dog"),字段名恰好叫 dog 时 @Resource 也能命中。生产上更推荐构造器注入,依赖不可变、容易测。

  4. 联合索引 ABC 与最左前缀:查询条件是 A = ? and C = ? 时,A 能走索引定位到区间,但 C 用不上(中间断了 B),优化器通常只用到 A 这一列做范围扫描,C 只能回表后过滤。可用的前缀是 A、AB、ABC;B = ?、BC = ? 这类不含 A 的条件完全走不了这个索引。补充一个常被追问的点:范围查询(>、<、between、like 'x%')之后的列也失去索引的有序性,只能用于过滤。

  5. 接口异常处理要给出一致的响应体设计:入参校验用 @Valid / @Validated 配合约束注解,失败时由 @RestControllerAdvice 全局异常处理器统一拦截 MethodArgumentNotValidException,返回 400 加结构化错误体(错误码、字段名、提示信息),不要让框架的默认堆栈泄露出去。业务异常自定义一个异常类,携带业务码,同样在全局处理器里映射成对应 HTTP 状态;「应返回一条却返回空」属于可预期的业务分支,通常在 service 层判断后抛业务异常或返回明确的业务码,而不是当成系统错误。要点是:错误码体系统一、对外不暴露内部细节、日志里保留完整上下文。

  6. 流式 AI 对话接口的选型:服务端单向持续推送、客户端不需要再往同一条连接发数据,首选 SSE(Content-Type: text/event-stream、Cache-Control: no-cache、Connection: keep-alive,代理层要关掉缓冲,Nginx 记得 X-Accel-Buffering: no)。要用 POST 是因为对话请求体里有消息历史、模型参数,GET 塞不下也不该塞;SSE 规范上基于 GET,但用 POST + text/event-stream 响应是实践中普遍支持的做法。相比普通 POST,它的响应是分块传输、不带 Content-Length,客户端要按 data: 逐条解析而不是等整个 body。如果是双向实时(用户中途打断、语音对话),WebSocket 更合适。

  7. 合并区间的写法与坑:先按左端点排序,然后一次遍历,维护当前区间 [l, r];下一个区间左端点小于等于 r 时合并(r = max(r, next.r)),否则把当前区间收进结果并开新区间。时间复杂度 O(n log n) 来自排序。容易错的是把判断写成严格小于、忘记 max(区间可能被完全包含),以及结果集初始化时先塞第一个区间的边界处理。