阿里巴巴Java开发手册要求集合初始化指定容量防扩容、禁止foreach修改结构、优先用isEmpty()判空、Map key须不可变且重写equals/hashCode、循环内避免重复计算。

阿里巴巴 Java 开发手册中对集合与循环的使用有明确、实用的约束,核心目标是提升代码可读性、避免空指针和并发问题、减少性能损耗。以下为关键约定的提炼与落地建议:
集合初始化时指定容量
避免默认容量导致多次扩容(如 ArrayList 默认 10,HashMap 默认 16 + 负载因子 0.75)。预估元素数量后显式传入初始容量,尤其在循环前创建集合时。
- ArrayList list = new ArrayList(expectedSize);
- HashMap map = new HashMap(expectedSize + 1); // +1 防止触发扩容阈值
- 若无法预估,宁可略高估,不建议用无参构造后反复 add
禁止在 foreach 中修改集合结构
for (String s : list) { list.remove(s); } 会抛 ConcurrentModificationException。需改用迭代器或普通 for 倒序遍历。
- 安全删除:Iterator
it = list.iterator(); while (it.hasNext()) { if (condition) it.remove(); } - 倒序 for:for (int i = list.size() - 1; i >= 0; i--) { if (condition) list.remove(i); }
- 批量操作优先考虑 Collection.removeIf()(JDK 8+)
集合判空优先用 isEmpty(),不用 size() == 0
语义更清晰,部分集合(如某些懒加载实现)size() 可能有额外开销;isEmpty() 是 O(1) 且意图明确。
- ✅ if (list != null && !list.isEmpty())
- ❌ if (list != null && list.size() > 0)
- 注意:判空前仍需 null 检查,除非已确保非空(如 Spring 注入的 Bean)
Map 的 key 必须保证不可变且正确重写 equals/hashCode
使用自定义对象作 key 时,若字段参与 equals 判断,必须同时参与 hashCode 计算,且该对象在放入 Map 后不得修改这些字段,否则导致 get 失效。
- 推荐用 final 字段 + Lombok @EqualsAndHashCode(仅 include 必要字段)
- 优先选用 JDK 自带不可变类型(String、Integer、LocalDate)作 key
- 避免用 ArrayList 或其他可变集合作 key
循环体内部避免重复计算、重复创建对象
将不变逻辑提到循环外,尤其是方法调用、集合 size()、正则 Pattern 编译等。
- ✅ int len = list.size(); for (int i = 0; i
- ✅ final Pattern pattern = Pattern.compile("abc"); for (String s : list) { pattern.matcher(s).find(); }
- 避免在 for 中 new SimpleDateFormat 等非线程安全对象(应改为 ThreadLocal 或使用 DateTimeFormatter)
















