本文标题大纲:
前言
在上篇文章 Java 集合框架(1)— 概述 中我们从大体上看了一下 Java 中的集合框架,包括 List
、Set
、Map
接口的一些介绍并且解释了一些接口中声明的相关方法用法。从这篇开始,我们将一起来看一下 Java 集合框架中一些具体的类的解析,了解它们的运行原理。先从 List
接口下的相关类开始。
还是先看一下上篇文章中的那张图,我们可以看到:在 Collection
接口下有一个名为 AbstractCollection
的抽象类,而 List
接口和 Set
接口下的具体类都直接 / 间接的继承了这个抽象类,我们还是先看一下这个抽象类:
AbstractCollection
来看看官方对这个类的描述:
This class provides a skeletal implementation of the Collection interface, to minimize the effort required to implement this interface.
To implement an unmodifiable collection,
the programmer needs only to extend this class and provide implementations for the iterator and size methods.
(The iterator returned by the iterator method must implement hasNext and next.)
To implement a modifiable collection, the programmer must additionally override this class’s add method (which otherwise throws an UnsupportedOperationException), and the iterator returned by the iterator method must additionally implement its remove method.
The programmer should generally provide a void (no argument) and Collection constructor, as per the recommendation in the Collection interface specification.
The documentation for each non-abstract method in this class describes its implementation in detail. Each of these methods may be overridden if the collection being implemented admits a more efficient implementation.
大概意思是:
该类提供了 Collection
接口的骨架实现,以最小化实现该接口所需的代价。
要实现不可修改的集合,开发者只需要继承这个类并实现 iterator()
方法和 size()
方法,即返回一个迭代器(实现了 hasNext
和 next
方法)用于遍历集合和一个表示集合元素个数的值。
为了实现可修改的集合,开发者必须另外重写该类的 add
方法(否则抛出 UnsupportedOperationException
异常),迭代器方法返回的迭代器还必须实现其 remove
方法。
开发者通常应该根据集合接口规范中的建议提供无参构造函数和以一个集合作为参数的构造函数。
该类中的每个非抽象方法的文档详细描述了它的实现。如果所实现的集合允许更有效的实现,则可以重写这些方法。
我们可以从上面的解释中的到一些信息:
1、这个类实现了 Collection
接口并且实现了一些集合通用的方法,这样的话具体集合类就可以直接 / 间接继承这个类,对一些已经实现的并且有效的方法无需再次实现,减轻了子类的负担;
2、继承这个类的子类必须重写其 iterator
和 size
这两个抽象方法,并且重写其中所有实现的方法中直接抛出了 UnsupportedOperationException
异常的方法(add
方法)。
3、如果子类可以提供更有效的方法实现,设计者鼓励开发者在子类中复写其中的一些方法,以获取更高的执行效率。
如上所述,我们可以看到 List
和 Set
接口的下的具体类都是直接 / 间接继承了这个抽象类。
我们来看看这个类的一些源码:
public abstract class AbstractCollection<E> implements Collection<E> {
// Query Operations
/**
* 返回一个包含了集合中所有元素的迭代器,用于遍历集合元素
*/
public abstract Iterator<E> iterator();
/**
* 返回集合中元素的数量
*/
public abstract int size();
/**
* 判断集合是否为空
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* 查找当前集合中是否存在等价于参数的元素(通过 equals 方法)
* 通过迭代器遍历集合并比对元素实现
*/
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
/**
* 这个方法返回包含集合中所有元素的数组,元素顺序通过迭代器遍历指定。
* 方法等同于:
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
* list.add(e);
* return list.toArray();
*/
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
// Modification Operations
/**
* 添加参数所指定的对象到当前集合中,子类应该实现该方法
*/
public boolean add(E e) {
throw new UnsupportedOperationException();
}
/**
* 从当前集合中移除第一个等价于参数的元素(通过 equals 方法判断等价),
* 通过迭代器遍历集合中的元素并判断,如果移除成功返回 true,否则返回 false
*/
public boolean remove(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
// Bulk Operations
/**
* 判断参数 c 所指向的集合中每一个元素是否都包含在当前集合中,
* 如果是,返回 true,否则返回 false
*/
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
/**
* 将参数 c 所指向的集合中的每一个元素都添加到当前集合中,
* 如果成功添加,返回 true,否则返回 false
*/
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
/**
* 移除所有当前集合中存在于参数 c 所指向集合的元素,
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();