1. 集合概述
1.1 什么是集合?
集合是Java中一种特殊的变量类型,作为容器可以同时存储多个数据元素。与基本数据类型变量只能存储单个值不同,集合提供了存储和管理对象组的有效方式。
1.2 集合与数组的区别
| 特性 | 数组 | 集合 |
|------|------|------|
| 长度 | 固定,声明后不可改变 | 动态可变,自动扩容 |
| 元素个数 | 无法直接获取实际存储元素数量 | 可通过size()方法获取准确数量 |
| 数据类型 | 可存储基本类型和引用类型 | 只能存储引用类型(对象) |
| 操作便利性 | 添加、删除操作复杂 | 提供丰富方法简化操作 |
| 元素特性 | 有序、可重复 | 可根据需求选择有序/无序、可重复/唯一 |
| 元素类型 | 只能存储同一类型元素 | 可存储多种类型元素(不推荐) |
2. 集合框架结构
2.1 Collection体系(单元素存储)
Collection (无序, 不唯一)
├── List (有序, 不唯一)
│ ├── ArrayList (数组实现,遍历高效)
│ └── LinkedList (链表实现,增删高效)
└── Set (无序, 唯一)
├── HashSet (哈希表实现)
└── TreeSet (红黑树实现,有序唯一)
2.2 Map体系(键值对存储)
Map (key无序唯一, value无序不唯一)
├── HashMap (哈希表实现)
└── TreeMap (红黑树实现,key有序)
2.3 工具类
- **Collections**: 集合操作工具类
- **Arrays**: 数组操作工具类
3. 核心知识点
3.1 增强for循环
增强for循环(foreach)简化了集合和数组的遍历,无需使用下标:
List<String> list = Arrays.asList("A", "B", "C");
for (String element : list) {
System.out.println(element);
}
3.2 泛型(Generics)
泛型提供了编译时类型安全检查,避免运行时类型转换错误:
// 不使用泛型
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0); // 需要强制转换
// 使用泛型
List<String> list = new ArrayList<>();
list.add("hello");
String s = list.get(0); // 自动类型转换
3.3 自动装箱与拆箱
自动转换基本类型和对应的包装类:
List<Integer> list = new ArrayList<>();
list.add(5); // 自动装箱: int -> Integer
int num = list.get(0); // 自动拆箱: Integer -> int
4. 核心接口详解
4.1 Collection接口
存储无序、不唯一元素的根接口:
// 常用方法
Collection<String> coll = new ArrayList<>();
// 添加元素
coll.add("张三");
coll.addAll(Arrays.asList("李四", "王五"));
// 删除元素
coll.remove("李四");
coll.clear(); // 清空
// 查询
int size = coll.size();
// 遍历
Iterator<String> iterator = coll.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 判断
boolean isEmpty = coll.isEmpty();
boolean contains = coll.contains("张三");
// 转换数组
Object[] array = coll.toArray();
4.2 List接口
有序、不唯一元素的集合接口:
List<String> list = new ArrayList<>();
// 位置相关操作
list.add(0, "b"); // 指定位置添加
list.addAll(0, Arrays.asList("c", "d"));
list.remove(1); // 按索引删除
list.set(0, "newValue"); // 修改指定位置元素
// 查询
String element = list.get(0);
int index = list.indexOf("b");
// 排序
list.sort(null); // 使用自然排序
4.3 Set接口
无序、唯一元素的集合接口,不包含重复元素。
5. 具体实现类
5.1 ArrayList
基于动态数组的实现,初始容量10,满时按1.5倍扩容:
ArrayList<String> list = new ArrayList<>();
// 确保初始容量
list.ensureCapacity(100);
// 子列表(视图)
List<String> subList = list.subList(1, 3);
// 方法引用遍历
list.forEach(System.out::println);
5.2 LinkedList
基于双向链表的实现,擅长添加和删除操作:
LinkedList<String> list = new LinkedList<>();
// 队列操作
list.addFirst("头元素");
list.addLast("尾元素");
String first = list.removeFirst();
String last = list.removeLast();
// 栈操作
list.push("栈元素");
String popped = list.pop();
String polled = list.poll();
**ArrayList vs LinkedList 对比**:
1. 底层结构:ArrayList使用动态数组,LinkedList使用双向链表
2. 访问效率:ArrayList随机访问高效(O(1)),LinkedList需遍历(O(n))
3. 增删效率:ArrayList中间增删需移动元素(O(n)),LinkedList只需修改指针(O(1))
4. 内存占用:ArrayList连续内存,LinkedList额外存储前后指针
5.3 HashSet
基于哈希表实现,使用hashCode()和equals()方法去重:
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 不会添加重复元素
**去重原理**:
1. 计算对象的hashCode()
2. 如果hashCode唯一,直接存入
3. 如果hashCode冲突,使用equals()比较对象内容
4. 内容相同则不存入,不同则存入(哈希冲突解决方案)
5.4 TreeSet
基于红黑树实现,元素有序排列:
```java
Set<String> set = new TreeSet<>();
set.add("orange");
set.add("apple");
set.add("banana");
// 元素按字典序排列: apple, banana, orange
6. 比较器
6.1 Comparable接口
自然排序接口,对象类实现该接口定义默认排序规则:
class Person implements Comparable<Person> {
private String name;
private int age;
@Override
public int compareTo(Person other) {
return this.age - other.age; // 按年龄排序
}
}
6.2 Comparator接口
比较器接口,用于定义多种排序规则:
Comparator<Person> nameComparator = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
};
// 使用比较器排序
Set<Person> people = new TreeSet<>(nameComparator);
7. 最佳实践与总结
1. **选择合适集合**:
- 需要快速随机访问:ArrayList
- 频繁增删操作:LinkedList
- 去重需求:HashSet
- 排序需求:TreeSet
2. **性能考虑**:
- 预估数据量大时,设置ArrayList初始容量避免频繁扩容
- 频繁查找操作考虑使用HashSet
3. **线程安全**:
- 基本集合实现非线程安全
- 多线程环境使用Collections.synchronizedXXX()或并发包集合
Java集合框架提供了强大而灵活的数据结构解决方案,理解各集合特性和适用场景是编写高效Java程序的关键。通过合理选择集合类型,可以显著提升代码性能和可维护性。
2914

被折叠的 条评论
为什么被折叠?



