Java 集合框架的核心接口 List、Set、Map 分别适用于不同的数据存储场景,选择正确的集合类型能显著提升代码性能和可维护性。
以下是它们的核心特点及典型使用场景:
1. List(有序、可重复)
特点:
- 有序性:元素按插入顺序存储,支持索引访问(
get(index)
)。 - 可重复:允许存储相同的元素。
- 常见实现类:
ArrayList
:基于动态数组,随机访问快(O(1)),尾部增删快,但中间插入/删除慢(O(n))。LinkedList
:基于双向链表,插入/删除快(O(1)),但随机访问慢(O(n))。CopyOnWriteArrayList
(线程安全):读操作无锁,写操作复制数组,适合读多写少场景。
使用场景:
- 需要保留顺序且允许重复的集合:
- 示例:商品购物车中的商品列表(同一商品可多次添加)。
List<Product> cart = new ArrayList<>(); cart.add(product1); cart.add(product2); // 允许重复
- 需要根据索引快速访问元素:
- 示例:分页查询结果。
List<User> userList = userDao.findByPage(pageNo, pageSize); User user = userList.get(3); // 直接访问第4个元素
- 需要频繁在头部/中间插入或删除:
- 示例:实现栈(Stack)或队列(Queue)结构(推荐用
LinkedList
)。
LinkedList<LogEntry> logQueue = new LinkedList<>(); logQueue.addFirst(newLog); // 头部插入
- 示例:实现栈(Stack)或队列(Queue)结构(推荐用
2. Set(无序、唯一)
特点:
- 唯一性:不允许重复元素(通过
equals()
和hashCode()
判断)。 - 无序性:不保证元素顺序(
LinkedHashSet
维护插入顺序,TreeSet
按排序规则存储)。 - 常见实现类:
HashSet
:基于哈希表,查询/插入/删除快(O(1)),但无序。LinkedHashSet
:在HashSet
基础上维护链表记录插入顺序。TreeSet
:基于红黑树,元素按自然顺序或Comparator
排序,操作时间复杂度 O(log n)。
使用场景:
- 需要自动去重的集合:
- 示例:统计文章关键词(避免重复记录同一词)。
Set<String> keywords = new HashSet<>(); keywords.add("Java"); keywords.add("Collection"); keywords.add("Java"); // 自动去重
- 需要快速判断元素是否存在:
- 示例:用户权限白名单校验。
Set<String> allowedRoles = new HashSet<>(Arrays.asList("admin", "editor")); if (allowedRoles.contains(userRole)) { // 允许访问 }
- 需要有序且去重的集合:
- 示例:按时间顺序展示用户最近访问的10个城市(用
LinkedHashSet
)。
Set<String> recentCities = new LinkedHashSet<>(); recentCities.add("北京"); recentCities.add("上海"); recentCities.add("北京"); // 去重,且保留插入顺序
- 示例:按时间顺序展示用户最近访问的10个城市(用
3. Map(键值对、键唯一)
特点:
- 键唯一性:每个键最多映射一个值(重复键会覆盖旧值)。
- 无序性:不保证键值对的顺序(
LinkedHashMap
维护插入顺序,TreeMap
按键排序)。 - 常见实现类:
HashMap
:基于哈希表,查询/插入/删除快(O(1))。LinkedHashMap
:维护插入顺序或访问顺序(适合实现 LRU 缓存)。TreeMap
:按键的自然顺序或Comparator
排序。ConcurrentHashMap
(线程安全):分段锁设计,适合高并发场景。
使用场景:
- 需要键值映射的存储结构:
- 示例:用户信息缓存(键:用户ID,值:用户对象)。
Map<Long, User> userCache = new HashMap<>(); userCache.put(1001L, new User(1001, "Alice")); User user = userCache.get(1001L); // 通过ID快速查找
- 需要按键排序:
- 示例:按字母顺序展示国家名称与代码(用
TreeMap
)。
Map<String, String> countryCodes = new TreeMap<>(); countryCodes.put("US", "United States"); countryCodes.put("CN", "China"); // 自动按键排序
- 示例:按字母顺序展示国家名称与代码(用
- 需要维护插入顺序或实现 LRU 缓存:
- 示例:记录用户最近浏览的商品(用
LinkedHashMap
维护访问顺序)。
Map<Long, Product> recentProducts = new LinkedHashMap<>(16, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry<Long, Product> eldest) { return size() > 100; // 最多保留100个最近访问的商品 } };
- 示例:记录用户最近浏览的商品(用
4. 快速选择指南
需求 | 推荐集合类型 | 示例场景 |
---|---|---|
保留顺序,允许重复 | ArrayList /LinkedList | 订单项列表、分页数据 |
快速去重,无需顺序 | HashSet | 用户ID集合、权限白名单 |
去重且保留插入顺序 | LinkedHashSet | 最近搜索记录、访问历史 |
键值对,快速查找 | HashMap | 缓存、配置项存储 |
键值对,按键排序 | TreeMap | 字典、按时间排序的事件记录 |
高并发读写 | ConcurrentHashMap | 多线程共享的缓存或计数器 |
总结
- List:处理有序、可重复的线性数据。
- Set:管理唯一性数据,支持快速存在性检查。
- Map:建立键值关联,高效通过键检索值。
根据具体需求(如顺序性、唯一性、排序规则、线程安全)选择合适的实现类,可显著优化代码性能和可读性。