Java集合框架(Java Collections Framework)是一个强大的、高度灵活的数据结构库,它为Java应用程序提供了组织、存储和操作对象集合的标准方法。
集合类体系结构
接口类:
Collection
: 是单例集合类的顶层接口,包括List、Set。Map
: 存储键值对(key-value pairs)的数据结构,不允许键重复,例如HashMap、TreeMap和LinkedHashMap。List
: 有序的、可重复的元素序列,允许通过索引进行访问,例如ArrayList、LinkedList和Vector。Set
: 不包含重复元素的集合,不保证元素的顺序,如HashSet、LinkedHashSet和TreeSet。
实现类:
ArrayList
:基于动态数组
实现,支持快速随机访问元素,但在插入和删除时可能需要移动大量元素。LinkedList
:基于链表
实现,插入和删除操作更快,但随机访问相对较慢。HashSet
:基于哈希表
实现,不允许重复元素,不保证元素的顺序。TreeSet
:基于红黑树
实现,不允许重复元素且自动排序。HashMap
:基于哈希表
实现,存储键值对,允许快速存取,键不能重复。TreeMap
:基于红黑树
实现,存储键值对,键不能重复且自动排序。
Collection集合
java.util.Collection
接口是所有单列集合(即只包含元素,不包含键值对)的顶层接口,它是Java集合框架的基础。它定义了集合对象的基本行为和操作,如添加元素、删除元素、检测集合是否为空、查询集合大小等。所有实现了 Collection 接口的类,如 List
和Set
,都遵循同样的基本操作。
创建Collection集合的对象
- 接口无法直接创建,需要使用多态的方式创建
代码示例:
//创建集合对象
Collection<String> c = new ArrayList<>();
Collection集合常用方法
添加元素:
boolean add(E e)
: 将指定元素添加到集合中,如果集合因添加而发生改变则返回 true,否则返回 false。
// 创建一个 ArrayList 实例,ArrayList 是 Collection 接口的实现类
Collection<String> list = new ArrayList<>();
// 添加元素
boolean res = list.add("Banana"); // 结果: true
boolean addAll(Collection<? extends E> c)
: 将指定集合中的所有元素添加到当前集合中,如果集合因添加而发生改变则返回 true,否则返回 false。
// 创建第一个 ArrayList 实例
Collection<String> list1 = new ArrayList<>();
list1.add("Apple");
list1.add("Banana");
list1.add("Cherry");
// 创建第二个 ArrayList 实例
Collection<String> list2 = new ArrayList<>();
list2.add("Durian");
list2.add("Elderberry");
list2.add("Fig");
// 使用 addAll() 方法将 list2 中的所有元素添加到 list1 中
Collection<String> collection1 = list1;
collection1.addAll(list2);
// 输出合并后的 list1
System.out.println("合并后的 list: " + list1);
删除元素:
boolean remove(Object o)
: 从集合中移除指定元素,如果集合因移除而发生改变则返回 true,否则返回 false。
// 创建第一个 ArrayList 实例
Collection<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 删除元素
list.remove("Banana");
System.out.println("删除'Banana'后: " + list);
boolean removeAll(Collection<?> c)
: 从当前集合中移除与指定集合中相交的所有元素,如果集合因移除而发生改变则返回 true,否则返回 false。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 创建另一个 ArrayList
Collection<String> toRemove = new ArrayList<>(Arrays.asList("Banana", "Date"));
// 输出原始 fruits 集合
System.out.println("原集合: " + list);
// 使用 removeAll() 方法移除 fruits 中与 toRemove 相同的元素
Collection<String> collection = list;
collection.removeAll(toRemove);
// 输出移除元素后的 fruits 集合
System.out.println("移除元素后的集合: " + list);
查询操作:
boolean contains(Object o)
: 判断集合中是否包含指定的元素。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 检查集合是否包含某个元素
System.out.println("集合中是否包含 'Banana'? " + list.contains("Banana"));
boolean containsAll(Collection<?> c)
: 判断当前集合是否包含指定集合中的所有元素。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 创建另一个 ArrayList
Collection<String> toContains = new ArrayList<>(Arrays.asList("Banana", "Date"));
boolean res = list.containsAll(toContains);
// 检查集合是否包含某个元素
System.out.println("第一个集合中是否包含第二个数组中的元素 ? " + res);
boolean isEmpty()
: 判断集合是否为空。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>();
// 判断集合是否为空
boolean res = list.isEmpty();
System.out.println("集合是否为空? " + res);// 结果为:true
int size()
: 返回集合中元素的个数。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 获取集合的长度
int size = list.size();
System.out.println("集合的长度为: " + size);
其它操作:
Object[] toArray()
: 返回一个包含集合中所有元素的数组。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 集合转数组
Object[] arr = list.toArray();
// 遍历数组
for (Object ele : arr) {
System.out.println(ele);
}
<T> T[] toArray(T[] a)
: 将集合转换为指定类型的数组。<T>
:表示泛型,代表集合中元素的实际类型,这个类型会被用来创建返回的数组。T[] a
:参数是一个对象数组,其元素类型与集合中的元素类型相同。如果传入的数组足够大(即长度大于等于集合的大小),那么集合的元素将被复制到这个数组中,并返回这个数组。如果传入的数组太小,系统会创建一个新的数组,大小正好足以容纳集合中的所有元素,并返回这个新数组。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 使用toArray()方法将集合转换为String数组
String[] array = list.toArray(new String[0]);
// 遍历数组
for (String str : array) {
System.out.println(str);
}
void clear()
: 清除集合中的所有元素。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 清空集合
list.clear();
System.out.println("输出清空后的集合: "+list); // 结果为: []
遍历Collection集合
Collection集合的遍历可以通过多种方式进行,以下是几种常见的遍历方法:
迭代器(Iterator)方式:
迭代器(Iterator)是用于遍历集合(包括Set
、List
等实现Collection
接口的类)中元素的一种设计模式。迭代器提供了一种统一的方式来访问集合中的元素,无需关心集合底层的具体实现。
迭代器的工作原理:
- 获取迭代器: 要遍历一个Collection集合,首先需要获取该集合的迭代器。这通常通过调用集合的
iterator()
方法实现:
Collection<String> collection = new ArrayList<>();
// ... 添加元素到collection ...
// 获取迭代器
Iterator<String> iterator = collection.iterator();
- 迭代过程: 迭代器提供了如下三个基本方法来进行遍历操作:
boolean hasNext()
: 检查集合中是否还有更多的元素可以迭代。如果有,则返回true,否则返回false。E next()
: 如果集合中还有元素,则返回下一个元素,并将迭代器内部的指针向前移动一位。如果没有更多的元素,将抛出NoSuchElementException
。void remove()
: 移除上次调用next()
方法返回的元素。注意,此方法只能在调用next()
之后使用,并且不能在调用next()
之前或两次next()
之间调用
使用迭代器遍历集合的示例:
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 获取迭代器
Iterator<String> iterator = list.iterator();
// 检测集合中是否还有元素, 取空停止循环
while (iterator.hasNext()){
// 取出元素,并把指针向后移动一位
String item = iterator.next();
System.out.println(item);
}
迭代器的优点:
- 抽象了遍历集合的行为,使得无论集合内部数据结构,都可以采用统一的方式来遍历元素。
- 提供了灵活的遍历控制,比如可以根据条件决定是否继续遍历或删除当前元素。
- 支持fail-fast机制,在迭代过程中,如果集合发生了结构性修改(如添加、删除元素),将会立即抛出
ConcurrentModificationException
,防止了数据一致性问题。
增强型for循环(foreach)方式:
增强型for循环(也称作foreach循环)是Java 5
引入的简洁遍历集合的方式,语法简洁易读,不需要显式调用迭代器。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// foreach方式遍历集合
for (String str : list) {
System.out.println(str);
}
Stream API 方式:
Java 8引入的Stream API
可以对集合进行流式处理,这里通过stream()
方法将集合转换为Stream,然后调用forEach()
方法进行遍历并处理每个元素。
// 创建一个 ArrayList
Collection<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 使用Stream API方式遍历集合
list.stream().forEach(System.out::println);
传统的for循环遍历索引(仅限List接口实现类):
对于List
接口的实现类,如ArrayList
、LinkedList
等,还可以通过传统for循环遍历索引的方式来访问元素,但这种方法并不适用于Set接口的实现类,因为Set接口的实现类不具备索引访问能力。
// 创建一个 ArrayList
ArrayList<String> list = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));
// 使用传统for循环遍历List集合
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}