Java 集合框架 (Collections Framework) 是 Java 平台提供的一组接口、实现类和算法,用于存储、操作和管理对象集合。 它是 Java 编程中最核心、最常用的 API 之一。
一、 集合框架概述 (Overview)
-
定义:
- 集合框架是一个统一的架构,用于表示和操作集合,允许它们独立于表示的细节进行操作。
- 集合框架提供了一组通用的接口和类,用于存储不同类型的对象,并提供了对这些对象进行添加、删除、查找、遍历、排序等操作。
-
优点:
- 减少编程工作量: 提供了现成的、高效的数据结构和算法,无需从头开始编写。
- 提高程序性能: 集合框架中的实现类经过了优化,具有良好的性能。
- 提高代码可读性和可维护性: 使用统一的接口和类,使代码更易于理解和维护。
- 促进代码复用: 集合框架中的接口和类可以在不同的程序中重复使用。
- 提供互操作性: 基于接口的集合框架允许不同类型的集合之间进行互操作。
-
组成部分:
- 接口 (Interfaces): 定义了集合的通用行为,例如
Collection,List,Set,Map,Queue,Deque等。 - 实现类 (Implementations): 提供了接口的具体实现,例如
ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap等。 - 算法 (Algorithms): 提供了一些常用的算法,例如排序、查找、打乱顺序等,这些算法可以用于操作各种类型的集合。
- 接口 (Interfaces): 定义了集合的通用行为,例如
二、 核心接口 (Core Interfaces)
Java 集合框架的核心接口主要分为两大类:
-
Collection接口:Collection接口是所有集合接口的根接口,它定义了集合的基本操作,例如添加元素、删除元素、判断是否包含元素、获取集合大小、遍历集合等。Collection接口的主要子接口:List接口: 有序集合,允许重复元素。Set接口: 无序集合,不允许重复元素。Queue接口: 队列,通常用于存储等待处理的元素(FIFO - 先进先出)。Deque接口: 双端队列,可以在两端添加和删除元素。
-
Map接口:Map接口用于存储键值对 (key-value pairs),每个键映射到一个值。Map接口中的键不能重复,值可以重复。Map接口的主要实现类:HashMapTreeMapLinkedHashMap
接口层次结构 (简化版):
Collection<E>
/ | \
/ | \
/ | \
/ | \
List<E> Set<E> Queue<E>
/ \ | / \
/ \ | / \
ArrayList LinkedList HashSet Deque<E>
| |
TreeSet ArrayDeque
PriorityQueue
Map<K, V>
/ | \
/ | \
HashMap TreeMap LinkedHashMap
三、 常用接口和实现类详解
-
Collection<E>接口:- 常用方法:
add(E e): 添加元素。addAll(Collection<? extends E> c): 添加另一个集合中的所有元素。remove(Object o): 删除元素。removeAll(Collection<?> c): 删除另一个集合中包含的所有元素。retainAll(Collection<?> c): 仅保留此集合中包含在另一个集合中的元素(交集)。clear(): 删除所有元素。contains(Object o): 判断是否包含指定元素。containsAll(Collection<?> c): 判断是否包含另一个集合中的所有元素。isEmpty(): 判断集合是否为空。size(): 返回集合中元素的数量。iterator(): 返回一个用于遍历集合的迭代器。toArray(): 将集合转换为数组。toArray(T[] a): 将集合转换为指定类型的数组。
- 常用方法:
-
List<E>接口:-
特点: 有序集合,允许重复元素。 可以通过索引访问元素。
-
常用方法 (除了
Collection接口的方法外):get(int index): 获取指定索引处的元素。set(int index, E element): 替换指定索引处的元素。add(int index, E element): 在指定索引处插入元素。remove(int index): 删除指定索引处的元素。indexOf(Object o): 返回指定元素第一次出现的索引。lastIndexOf(Object o): 返回指定元素最后一次出现的索引。subList(int fromIndex, int toIndex): 返回指定范围的子列表。listIterator(): 返回一个列表迭代器,可以双向遍历列表,并修改列表。
-
常用实现类:
ArrayList: 基于动态数组实现,查询快,插入/删除慢 (尤其是在中间插入/删除)。 非线程安全。LinkedList: 基于双向链表实现,插入/删除快 (尤其是在中间插入/删除),查询慢。 非线程安全。Vector: 类似于ArrayList,但线程安全 (方法都使用synchronized修饰)。 性能较低。Stack: 继承自Vector,表示栈。
-
-
Set<E>接口:- 特点: 无序集合,不允许重复元素。
- 常用方法 (与
Collection接口基本相同): - 常用实现类:
HashSet: 基于哈希表实现,无序,查找、添加、删除速度快。 非线程安全。LinkedHashSet: 基于哈希表和链表实现,按照插入顺序排序。 非线程安全。TreeSet: 基于红黑树实现,有序 (可以按照自然顺序或自定义比较器排序)。 非线程安全。
-
Queue<E>接口:-
特点: 队列,通常用于存储等待处理的元素,遵循 FIFO (先进先出) 原则。
-
常用方法:
add(E e)/offer(E e): 添加元素到队尾 (前者在队列满时抛出异常,后者返回false)。remove()/poll(): 移除并返回队头元素 (前者在队列为空时抛出异常,后者返回null)。element()/peek(): 返回队头元素,但不移除 (前者在队列为空时抛出异常,后者返回null)。
-
常用实现类:
LinkedList: 也实现了Queue接口,可以用作队列。PriorityQueue: 优先级队列,元素按照优先级排序。ArrayBlockingQueue: 基于数组的有界阻塞队列。LinkedBlockingQueue: 基于链表的可选有界阻塞队列。PriorityBlockingQueue: 无界阻塞优先级队列。DelayQueue: 延迟队列,元素只有在延迟时间到期后才能被取出。SynchronousQueue: 同步队列,每个插入操作必须等待另一个线程的移除操作,反之亦然。
-
-
Deque<E>接口:-
特点: 双端队列 (Double Ended Queue),可以在两端添加和删除元素。
-
常用方法:
addFirst(E e),offerFirst(E e)addLast(E e),offerLast(E e)removeFirst(),pollFirst()removeLast(),pollLast()getFirst(),peekFirst()getLast(),peekLast()
-
常用实现类:
LinkedList: 也实现了Deque接口。ArrayDeque: 基于数组实现的双端队列。
-
-
Map<K, V>接口:-
特点: 存储键值对 (key-value pairs),键不能重复,值可以重复。
-
常用方法:
put(K key, V value): 添加键值对。get(Object key): 根据键获取值。remove(Object key): 根据键删除键值对。containsKey(Object key): 判断是否包含指定的键。containsValue(Object value): 判断是否包含指定的值。isEmpty(): 判断 Map 是否为空。size(): 返回 Map 中键值对的数量。keySet(): 返回所有键的Set集合。values(): 返回所有值的Collection集合。entrySet(): 返回所有键值对的Set集合 (每个元素是一个Map.Entry对象)。
-
常用实现类:
HashMap: 基于哈希表实现,无序,查找、添加、删除速度快。 非线程安全。 允许null键和null值。TreeMap: 基于红黑树实现,有序 (可以按照自然顺序或自定义比较器排序)。 非线程安全。LinkedHashMap: 基于哈希表和链表实现,按照插入顺序或访问顺序排序。 非线程安全。Hashtable: 类似于HashMap,但线程安全 (方法都使用synchronized修饰)。 性能较低。 不允许null键和null值。ConcurrentHashMap: 线程安全的HashMap,使用分段锁 (Segment Locking) 或 CAS 操作实现高效的并发访问。
-
四、常用算法 (Collections Class)
java.util.Collections 类提供了一组静态方法,用于操作集合:
- 排序:
sort(List<T> list),sort(List<T> list, Comparator<? super T> c) - 查找:
binarySearch(List<? extends Comparable<? super T>> list, T key),binarySearch(List<? extends T> list, T key, Comparator<? super T> c) - 最大/最小值:
max(Collection<? extends T> coll),min(Collection<? extends T> coll),max(Collection<? extends T> coll, Comparator<? super T> comp),min(Collection<? extends T> coll, Comparator<? super T> comp) - 反转:
reverse(List<?> list) - 打乱顺序:
shuffle(List<?> list) - 填充:
fill(List<? super T> list, T obj) - 复制:
copy(List<? super T> dest, List<? extends T> src) - 同步:
synchronizedCollection(Collection<T> c),synchronizedList(List<T> list),synchronizedSet(Set<T> s),synchronizedMap(Map<K,V> m)(用于创建线程安全的集合) - 不可修改:
unmodifiableCollection(Collection<? extends T> c),unmodifiableList(List<? extends T> list),unmodifiableSet(Set<? extends T> s),unmodifiableMap(Map<? extends K,? extends V> m)(用于创建不可修改的集合)
五、迭代器 (Iterator)
-
Iterator<E>接口: 用于遍历集合中的元素。hasNext(): 判断是否还有下一个元素。next(): 返回下一个元素。remove(): 删除迭代器最后一次返回的元素 (可选操作,并非所有迭代器都支持)。
-
ListIterator<E>接口:List接口特有的迭代器,支持双向遍历,并可以修改列表。hasPrevious(): 判断是否还有上一个元素。previous(): 返回上一个元素。nextIndex(): 返回下一个元素的索引。previousIndex(): 返回上一个元素的索引。set(E e): 替换迭代器最后一次返回的元素。add(E e): 在迭代器当前位置插入一个元素。
-
增强 for 循环 (for-each 循环): 简化了集合的遍历. 本质上是使用了 Iterator.
List<String> list = Arrays.asList("a", "b", "c"); for (String s : list) { System.out.println(s); }
六、泛型 (Generics)
- 集合框架广泛使用了泛型,可以指定集合中存储的元素类型,提高类型安全性和代码可读性。
- 例如:
List<String>表示一个只能存储String类型元素的列表。 - 泛型的好处:
- 类型安全: 在编译时检查类型错误,避免运行时类型转换异常。
- 代码可读性: 代码更清晰,更容易理解。
- 代码复用: 可以编写更通用的代码,处理不同类型的集合。
七、并发集合 (Concurrent Collections)
java.util.concurrent 包提供了一组线程安全的集合类,用于多线程环境:
ConcurrentHashMap: 线程安全的HashMap。CopyOnWriteArrayList: 线程安全的List,适用于读多写少的场景。CopyOnWriteArraySet: 线程安全的Set,适用于读多写少的场景。ConcurrentLinkedQueue: 线程安全的无界队列。ConcurrentLinkedDeque: 线程安全的无界双端队列。- 阻塞队列 (BlockingQueue):
ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue,DelayQueue,SynchronousQueue
八、最佳实践
-
选择合适的集合类型: 根据你的需求选择最合适的集合接口和实现类。 考虑以下因素:
- 是否需要有序?
- 是否允许重复元素?
- 是否需要根据键查找值?
- 是否需要线程安全?
- 插入、删除、查找的频率?
-
使用泛型: 始终使用泛型来指定集合中存储的元素类型,提高类型安全性。
-
面向接口编程: 使用接口类型(例如
List,Set,Map)声明变量,而不是使用具体的实现类类型。 -
使用增强 for 循环: 优先使用增强 for 循环遍历集合,代码更简洁。
-
注意并发问题: 在多线程环境下,使用线程安全的集合类,或者使用同步机制来保护非线程安全的集合。
-
避免在迭代过程中修改集合: 在使用迭代器遍历集合时,不要直接修改集合的结构(例如添加或删除元素),否则可能会抛出
ConcurrentModificationException。 可以使用迭代器的remove()方法删除元素,或者使用ListIterator修改列表。 -
了解集合的性能特征: 不同的集合实现类具有不同的性能特征,了解这些特征可以帮助我们选择最合适的集合。
-
使用
Collections工具类: 充分利用Collections工具类提供的各种静态方法,简化集合操作。 -
合理设置集合的初始容量: 对于
ArrayList、HashMap等基于数组的集合,在创建时指定一个合适的初始容量,可以减少扩容操作,提高性能。 -
注意 null 值: 一些集合 (例如
HashMap,ArrayList) 允许null值, 一些集合 (例如TreeMap,Hashtable) 不允许。
总结
Java 集合框架是 Java 编程中非常重要的一个部分,它提供了一组强大、灵活、高效的工具来处理对象集合。
1113

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



