购物车数量边界控制需集合与文件协同:集合层用原子操作和clampquantity统一校验,文件层读写全程再校验并双向同步,确保数据合法不脱节。

用集合与文件逻辑控制购物车数量边界,核心是把“数据结构约束”和“持久化校验”拧成一股绳:集合负责每次操作的原子性与合法性,文件(或 localStorage / 数据库)负责落地时的兜底清洗,二者不脱节、不越权。
集合层:用原子操作封住非法中间态
无论用 Map 还是 List 存商品,数量变更不能裸写字段,必须走封装方法:
- Map
场景:加购用 merge(key, 1, Integer::sum),减购用 computeIfPresent(key, (k, v) -> Math.max(0, v - 1)),设值直接 put(key, clampQuantity(target, 0, stock)) - List
场景:每个 CartItem 提供 updateQuantity(int newQty) 方法,内部强制执行 this.quantity = Math.max(0, Math.min(newQty, stock)),构造时也校验,避免 new CartItem(p, -3) 这类脏实例入集合 - 所有数量规则(下限 0/1、上限库存、限购数)统一收口到 clampQuantity(int raw, int min, int max),不分散在按钮、输入框、导入逻辑里
文件层:读写全程带边界意识,不信任任何外部数据
localStorage 或 JSON 文件不是“透明管道”,而是需要主动消毒的入口:
- 加载时:先读原始值 → 再过 clampQuantity → 最后进集合。例如从 localStorage.getItem("cart") 解析出 { "p123": -5, "p456": 999 },必须对每个 quantity 调用 clampQuantity(-5, 0, stock) 和 clampQuantity(999, 0, stock),再塞进 cart map
- 保存时:不直接序列化原始集合,而是 遍历 entry,对每个 quantity 再次 clamp 后写入。防止内存中已修正的数据,在落盘前被其他线程/逻辑意外污染
- 清空或重置时:clear() 后立即同步派生状态(如 totalQty = 0),并检查是否需触发二次清理(如批量删完只剩 quantity=0 的项,就主动 cart.clear())
边界联动:集合变动即触发文件刷新,文件异常即重置集合
二者不是单向同步,而是双向守门:
- 每次调用 updateQuantity / merge / compute 等方法后,立刻调用 persistToStorage(),哪怕只是 localStorage.setItem("cart", JSON.stringify(cart)) —— 延迟写入容易在崩溃时丢数据
- 若从文件读取失败(JSON parse error)、或解析后发现关键字段缺失(如 quantity 为 null),不抛异常也不静默跳过,而是初始化一个空且合法的 cart,并记录 warn 日志
- 服务端返回库存变更时,前端应触发一次 reclampAllQuantities():遍历当前 cart 所有商品,按最新 stock 重新 clamp,再持久化 —— 避免用户本地存着超库存的数量继续下单
不复杂但容易忽略:集合管“怎么变”,文件管“变成啥”,中间没有灰色地带。











