Java集合框架是Java标准库中用于统一管理和操作数据集合的核心组件,它提供了一套设计优良、功能丰富的接口和实现类,开发者可以根据数据的特性、操作需求选择合适的集合类型,实现高效的数据存储和访问。

Java集合框架的核心体系
Java集合框架主要分为两大顶层接口:Collection和Map。Collection接口用于存储单列数据,其下又衍生出List、Set、Queue等子接口;Map接口用于存储键值对形式的双列数据,常见的实现类有HashMap、TreeMap等。
Collection接口下的常用实现类
- List系列:有序可重复,允许存储null值,常用实现类有
ArrayList、LinkedList。ArrayList底层基于动态数组实现,查询速度快,增删中间元素效率低;LinkedList底层基于双向链表实现,增删首尾元素效率高,查询需要遍历。 - Set系列:无序不可重复,常用实现类有
HashSet、TreeSet。HashSet底层基于HashMap实现,依靠元素的hashCode()和equals()方法判断重复,查询插入效率高;TreeSet底层基于红黑树实现,支持元素自然排序或自定义排序。
Map接口下的常用实现类
HashMap:底层基于数组+链表+红黑树实现,键值对允许null,查询插入效率高,无序存储。TreeMap:底层基于红黑树实现,键支持排序,不允许null键。LinkedHashMap:继承自HashMap,额外维护双向链表记录插入顺序,可保证遍历顺序和插入顺序一致。
不同场景下的集合选择技巧
选择集合类型时首先要明确业务需求,以下是常见场景的选型建议:
| 业务场景 | 推荐集合类型 | 选型原因 |
|---|---|---|
| 存储有序可重复的用户列表,频繁查询 | ArrayList | 动态数组查询时间复杂度O(1),满足频繁查询需求 |
| 存储需要频繁增删首尾的任务队列 | LinkedList | 链表增删首尾元素时间复杂度O(1),效率更高 |
| 存储不重复的商品ID集合,快速判断是否存在 | HashSet | 哈希表查询时间复杂度接近O(1),去重和判断存在效率高 |
| 存储需要按插入顺序遍历的配置项键值对 | LinkedHashMap | 维护插入顺序,遍历顺序和插入顺序一致 |
| 存储需要按分数排序的学生成绩键值对 | TreeMap | 红黑树结构支持键自动排序,无需额外排序操作 |
集合使用的高效技巧
合理初始化集合容量
很多集合类在元素超过初始容量时会触发扩容,扩容过程需要复制原有数组,会带来性能开销。如果能预估存储元素的数量,建议初始化时指定容量,比如ArrayList默认初始容量是10,若需要存储100个元素,可直接指定初始容量为100:
import java.util.ArrayList;
import java.util.List;
public class CollectionDemo {
public static void main(String[] args) {
// 预估需要存储100个元素,指定初始容量避免频繁扩容
List<String> userList = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
userList.add("用户" + i);
}
System.out.println("集合大小:" + userList.size());
}
}
正确使用Set去重
使用HashSet存储自定义对象去重时,必须重写对象的hashCode()和equals()方法,否则默认的hashCode()基于对象内存地址计算,即使内容相同也会被认为是不同元素:
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class User {
private String id;
private String name;
public User(String id, String name) {
this.id = id;
this.name = name;
}
// 重写hashCode,基于id和name计算
@Override
public int hashCode() {
return Objects.hash(id, name);
}
// 重写equals,判断id和name都相同则为同一对象
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
User user = (User) obj;
return Objects.equals(id, user.id) && Objects.equals(name, user.name);
}
}
public class SetDemo {
public static void main(String[] args) {
Set<User> userSet = new HashSet<>();
userSet.add(new User("1", "张三"));
userSet.add(new User("1", "张三")); // 内容相同,不会被重复添加
System.out.println("集合大小:" + userSet.size()); // 输出1
}
}
遍历集合时避免频繁修改
使用普通for循环遍历List时如果进行增删操作,可能会导致索引错乱或漏遍历,建议使用迭代器或者增强for循环配合条件判断,或者使用removeIf()方法:
import java.util.ArrayList;
import java.util.List;
public class TraverseDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
// 使用removeIf批量删除符合条件的元素,避免遍历修改问题
list.removeIf(item -> "b".equals(item) || "d".equals(item));
System.out.println(list); // 输出[a, c]
}
}
注意线程安全场景的集合选择
普通集合类如ArrayList、HashMap都是非线程安全的,多线程环境下并发修改可能会出现数据不一致问题。如果需要线程安全的集合,可以选择Vector、Hashtable这类古老的实现,或者使用Collections工具类的同步包装方法,更推荐的是使用java.util.concurrent包下的并发集合,比如ConcurrentHashMap、CopyOnWriteArrayList,它们的性能比同步包装的集合更好。
总结
Java集合框架提供了丰富的类库满足不同的数据存储需求,开发者需要熟悉各个集合的底层实现和特性,根据业务场景选择合适的集合类型,同时掌握初始化容量、正确去重、安全遍历等技巧,就能实现高效的数据存储,提升程序的运行性能。