集合放大integer缓存边界效应:用==比较集合中元素时,-128~127范围内因缓存复用返回true,范围外返回false;应统一用objects.equals()或依赖equals()/hashcode()的集合方法。

集合本身不参与数值比较的语义判断,但它天然放大包装类缓存机制的边界效应——当你把 Integer 放进 HashSet、HashMap 或 ArrayList 后再做 == 比较,就等于把“对象复用”和“值相等”两个维度强行拉到同一平面,红线立刻浮现。
集合是缓存行为的放大器
HashSet 和 HashMap 的 key 依赖 hashCode() 和 equals(),而 ArrayList 存储的是引用。但开发者常误用 == 判断集合中元素是否“相同”,这会直接暴露缓存范围:
- Integer a = 127, b = 127;放入 ArrayList 后取出来比较:a == b → true(因缓存复用)
- Integer c = 128, d = 128;同样操作:c == d → false(两个独立对象)
- 若用 contains() 或 get(key) 方法,则完全依赖 equals() 和 hashCode(),结果始终一致——说明集合正确履行了契约
Map 的 key 场景最易踩坑
用 Integer 作 HashMap 的 key 看似自然,但若在业务中混用 == 判断 key 是否命中,就会在 -128~127 外失效:
- Map
map = new HashMap(); map.put(127, "ok"); map.containsKey(127) → true(自动调用 equals) - 但若写成 map.keySet().stream().filter(k -> k == 127).findAny(),逻辑看似等价,实则依赖装箱路径——127 被自动装箱为缓存对象,能匹配;128 就可能漏判
- 更危险的是:map.put(new Integer(127), "bad"),这个 new 出的对象永远不等于缓存中的 127,导致重复 key
List 和 Set 中的隐式比较陷阱
遍历 List 时用 == 判断相邻元素是否“相等”,或用 Set 去重却依赖 == 行为,都会让缓存边界变成运行时 bug:
- List
list = Arrays.asList(127, 127, 128, 128); list.get(0) == list.get(1) → true;list.get(2) == list.get(3) → false - Set
set = new HashSet(); set.add(127); set.add(new Integer(127));结果 size 是 2 —— 因为 new Integer(127).hashCode() 虽与缓存对象相同,但 equals() 仍成立,实际不会重复;真正风险在于开发者误以为 == 可替代 equals() - 建议统一用 Objects.equals(a, b) 替代 a == b,尤其在集合遍历、分组、去重逻辑中
缓存感知型集合封装建议
若业务频繁使用 Integer 集合且需高性能比较,可封装一层语义明确的工具:
- 提供 of(int...) 工厂方法,内部统一调用 Integer.valueOf(),避免 new Integer
- 暴露 asValueList() 返回 List
,但配套提供 equalsByValue(List , List ) 方法 - 对状态码、索引类小整数集合,可预加载 -128~127 缓存实例池,确保所有创建路径可控











