浩鲸 Java 一面:HashMap、数据权限与同步水位线
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 能否介绍自己的背景和项目?
- 字符串字面量赋值与 new String() 有什么区别?
- Java 8 HashMap.put() 的完整流程是什么?
- HashMap 为什么不从一开始就使用红黑树?
- 桶内链表较长但数组容量小于 64 时,为什么优先扩容?
- 扩容后节点为什么只会留在原索引或移动到原索引加旧容量的位置?
- 泛型 PECS 原则是什么,extends 与 super 各适合什么场景?
- Redis 为什么快,串行执行命令怎样服务大量并发连接?
- Redis 怎样清理过期 key?
- 怎样用有序集合设计延迟任务?
- Pub/Sub 用作消息队列有什么问题,Stream 与专业消息队列又有哪些区别?
- Spring Boot 自动配置怎样工作,条件注解起什么作用?
- 外部化配置有哪些来源,优先级怎样确定?
- Spring Bean 的生命周期是什么,BeanPostProcessor 在什么位置执行、作用范围如何?
- Spring AOP 的原理是什么,JDK 动态代理与 CGLIB 有何区别?
- 同类调用、final 方法、static 方法和非 Spring Bean 分别会给代理带来什么限制?
- 是否使用过 Spring AI,接入模型做过什么?
- 大模型幻觉是什么,为什么出现,怎样缓解?
- RAG 是什么,为什么能为回答补充依据?
- 数据权限重构解决了什么问题,为什么引入自定义权限注解?
- AOP 怎样生成和注入权限 SQL,为什么改用 dataScope 表达权限?
- 多角色的数据权限怎样合并,缓存怎样与权限计算配合?
- 为什么把权限计算从 AOP 中抽出,跨 Service 应传 SQL 还是可见部门集合?
- 数据同步为什么使用模板方法模式?
- 水位线、分页拉取、转换与批量写入怎样串起来?
- 为什么全部分页成功后才能推进水位线,提前推进后宕机会怎样?
- 怎样让同步任务不漏数据,并处理重复拉取?
- OAuth2 登录的完整流程是什么,state 有什么用途?
- 为什么需要关联浏览器标识?
- 一次性 ticket 为什么放在 Redis,怎样通过 Lua 原子消费?
- ticket 换 JWT 是怎样的过程,能否改成建立 Session?
- Session 与 JWT 有何区别,为什么项目选择 JWT?
- 使用 JWT 是否就不存在会话管理需求?
- 足底压力项目解决什么问题,你负责哪部分,数据采集后经过哪些步骤?
- 资源访问怎样鉴权,为什么不直接暴露原始文件路径?
- 临时资源副本何时生成、存在哪里,是否每次访问都需要物理复制?
- 这套文件访问方案怎样优化,你了解哪些文件系统知识?
《参考解析》
同步水位线是完成位置
先确定这一轮的读取范围,分页处理成功并持久化后,再记录完成位置。只拿到第一页就推进水位线,宕机重启后可能直接跳过剩余页。重复处理可以通过稳定业务键和幂等写入控制,已经跳过的数据却不会自动回来。分页排序还需要唯一键作补充,避免相同时间戳的数据落在边界时遗漏。
权限缓存要带上权限上下文
权限结果通常与用户、角色、组织关系和规则版本有关,不能用一个过于粗糙的 key 让不同权限的人共享结果。业务服务之间传递可见范围或结构化条件,比传一段任意 SQL 更便于检验与复用;最终拼接查询时仍需绑定参数。权限发生变更后,缓存更新与失效方式也要一起说明。
HashMap 扩容利用容量翻倍
JDK 8 的桶数组容量按二的幂组织。容量翻倍后,索引计算只多检查一位:该位为零时仍在原位置,否则移动旧容量那么远。小表中的碰撞可能通过扩容得到缓解,树节点又有额外空间与维护成本,因此不会把每个桶一开始都建成树。
一次性凭证要把检查与消费合起来
若先读 ticket、再单独删除,两个请求可能同时读到有效值。将检查和消费放入同一段原子操作,才能控制一个凭证只被成功使用一次。凭证还需要期限及使用场景绑定。JWT 的签名只说明令牌未被篡改,退出登录、撤销权限和设备会话依然需要明确设计。
RAG 给的是可核对的材料
检索到相关文档后,模型有机会基于材料回答;但检索错误、材料过时、遗漏例外条件或生成时误读,都可能造成错误。评估时分别检查有没有找到正确证据,以及回答是否被证据支持,不能把“用了 RAG”当成正确率保证。