Appearance
Java 集合怎么选:List、Set、Map 与常见实现的取舍
Java 集合最容易踩的坑,不是不会写,而是选型太随手。
很多项目里集合都能跑,但一旦数据量变大、并发上来或者顺序要求变复杂,问题就会慢慢出现。
先说结论
先记住一套够用的默认判断:
- 需要按下标访问、读多写少,优先
ArrayList - 需要去重,优先
HashSet - 需要键值映射,优先
HashMap - 需要保留插入顺序,优先
LinkedHashMap - 需要排序,考虑
TreeMap - 并发读写共享
Map,优先ConcurrentHashMap
真正需要 LinkedList 的业务场景,其实远比想象中少。
一、先按接口理解集合
集合大致先分三类:
List:有序、可重复Set:无重复Map:键值对映射
先定接口,再选具体实现,通常会更清楚。
二、List 怎么选
1. ArrayList
大多数情况下,它都是默认首选。
优点:
- 连续内存,随机访问快
- 遍历性能通常更好
- API 直观,使用成本低
注意点:
- 中间位置插入和删除,需要搬移元素
- 扩容会带来数组复制成本
适合:
- 读多写少
- 结果集、分页数据、内存列表处理
2. LinkedList
很多教程会说它“增删快”,但这句话很容易让人误解。
更准确地说:
- 只有在你已经拿到目标节点位置时,局部插入删除才更有优势
- 如果还是要先遍历定位,整体不一定比
ArrayList更快
再加上:
- 随机访问慢
- 节点对象额外占内存
- CPU 缓存友好性差
所以普通业务里,它并不是默认优选。
更适合:
- 需要双端队列语义
- 频繁头尾插入删除
三、Set 怎么选
1. HashSet
本质上底层依赖 HashMap。
适合:
- 去重
- 判断元素是否存在
不保证顺序。
2. LinkedHashSet
如果你既想去重,又希望保留插入顺序,可以用它。
3. TreeSet
如果你需要元素自动排序,可以考虑 TreeSet。
代价是:
- 插入、删除、查询成本通常高于哈希结构
- 元素需要可比较,或者提供比较器
四、Map 怎么选
1. HashMap
默认首选。
适合:
- 绝大多数普通键值映射场景
注意:
- 无序
- 线程不安全
2. LinkedHashMap
如果你需要保留插入顺序,或者做简单 LRU 思路的缓存容器,它很实用。
3. TreeMap
按 key 排序。
适合:
- 范围查询
- 有序输出
4. ConcurrentHashMap
并发环境下共享 Map 的默认优选。
相比老的 Hashtable:
- 并发性能更好
- 锁粒度更细
- 更适合高并发读写
五、几个高频误区
1. 线程安全就直接用 Hashtable
现在大多数场景下,更该优先考虑 ConcurrentHashMap。
2. 觉得 LinkedList 一定更适合增删
如果你的操作模式还是“查到位置再增删”,它未必更快。
3. 把集合当缓存,但不考虑上限
很多内存问题,最后根源就是一个 Map 一直塞数据却没有淘汰策略。
4. 需要有序,却默认用了 HashMap
如果顺序真有业务意义,要显式使用 LinkedHashMap 或 TreeMap。
六、工程里更实用的选择方式
如果只是做普通业务开发,可以先用这套默认思路:
List默认ArrayListSet默认HashSetMap默认HashMap- 需要顺序用
LinkedHashMap - 需要并发用
ConcurrentHashMap - 需要排序再考虑
TreeMap
只有当数据结构语义真的明确匹配时,再选 LinkedList、TreeSet 这类更特殊的实现。
一句话总结
集合选型最重要的不是背实现细节,而是先想清楚业务到底要什么:
- 要不要重复
- 要不要顺序
- 要不要排序
- 会不会并发访问
把这四件事想清楚,绝大多数集合选型都不会太偏。