线程安全应避免ArrayList/HashMap,改用CopyOnWriteArrayList、ConcurrentHashMap或AtomicInteger;HashMap需预设容量和负载因子;优先选ArrayDeque而非LinkedList;业务场景用不可变集合或EnumMap等专用结构。

需要线程安全时别直接用 ArrayList 或 HashMap
它们不是线程安全的,多线程写入会出 ConcurrentModificationException 或数据丢失。常见错误是加了 synchronized 块但没覆盖所有访问路径,导致伪安全。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 读多写少:优先用
Collections.unmodifiableList()配合外部同步,或直接用CopyOnWriteArrayList(注意写操作开销大) - 读写均衡:用
ConcurrentHashMap,它分段锁/ CAS 实现,比Hashtable性能好得多 - 简单计数场景:用
AtomicInteger或LongAdder,比包装成ConcurrentHashMap更轻量
HashMap 的初始容量和负载因子不能只看默认值
默认 initialCapacity=16、loadFactor=0.75,意味着插入第 13 个元素就触发扩容。频繁扩容会复制整个桶数组,GC 压力明显上升。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 预估大小:比如确定存 1000 个键值对,设
new HashMap(1024)(向上取 2 的幂),避免中途扩容 - 高冲突场景(如大量字符串哈希相近):可适当调低
loadFactor(如 0.5),以空间换查询稳定性 - 注意 JDK 8+ 的红黑树转换阈值是 8,但前提是桶内链表长度 ≥8 且
table.length ≥ 64,小容量下仍走链表,性能差异明显
频繁增删首尾元素时,LinkedList 并不比 ArrayDeque 快
很多人以为 LinkedList 是为双向队列设计的,实际它每个节点都要额外分配对象,内存碎片多,CPU 缓存不友好。JDK 自己的栈、队列工具类(如 Arrays.asList().stream().collect(Collectors.toCollection(ArrayDeque::new)))也倾向用 ArrayDeque。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 当需要
addFirst()/removeLast()等操作时,无条件选ArrayDeque -
LinkedList唯一合理场景:在已知节点引用的前提下做listIterator().add()插入(极少见) - 若必须用链表语义且需随机访问,不如用
ArrayList+ 批量subList()操作,现代 JVM 对连续内存优化远胜指针跳转
业务语义明确时,优先用不可变集合或专用结构
比如“配置项只读映射”“用户权限集合”“枚举状态集合”,硬套 HashMap 或 HashSet 容易漏掉空值、重复添加、意外修改等边界问题。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 静态常量映射:用
Map.of("k1", v1, "k2", v2)(Java 9+)或ImmutableMap.of()(Guava),编译期检查、零运行时开销 - 有限枚举键:用
EnumMap,内部是数组索引,比HashMap快 3–5 倍,且类型安全 - 去重且有序:别先
new HashSet再转TreeSet,直接用TreeSet或排序后LinkedHashSet保插入序
HashMap 可能悄悄吃掉 20% 的 Young GC 时间。









