Collection接口
Collection 接口是 JCF 层次结构的根(尽管其还继承自 Iterable 接口)其定义了一些集合的相关操作方法,源码及简单注释如下:
package java.util;
public interface Collection<E> extends Iterable<E> {
/**
* 返回此集合中的元素个数。
*/
int size();
/**
* 判断此集合是否不包含元素。
*/
boolean isEmpty();
/**
* 判断此集合是否包含指定元素。
*/
boolean contains(Object o);
/**
* 迭代器,详解见下面迭代器模式一节
*/
Iterator<E> iterator();
/**
* 返回包含此集合中所有元素的数组。
* 若集合是有序的,则需以相同顺序返回。
*/
Object[] toArray();
/**
* 返回包含此集合中所有元素的数组,并可指定返回数组的运行时类型。
* 若集合是有序的,则需以相同顺序返回。
*/
<T> T[] toArray(T[] a);
/**
* 在此集合中添加指定元素。
*/
boolean add(E e);
/**
* 从此集合中移除指定元素。
*/
boolean remove(Object o);
/**
* 如果此集合包含指定集合中的所有元素,则返回 true。
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合中的所有元素都添加到此集合中。
* 若此集合因此调用而发生改变则返回 true。
*/
boolean addAll(Collection<? extends E> c);
/**
* 从此集合中移除那些也包含在指定集合中的所有元素。
*/
boolean removeAll(Collection<?> c);
/**
* 从此集合中移除那些未包含在指定集合中的所有元素。
*/
boolean retainAll(Collection<?> c);
/**
* 移除此集合中的所有元素。
*/
void clear();
/**
* 若希望实现值比较可重写 equals 方法。
*/
boolean equals(Object o);
/**
* 若重写 equals 方法则必须重写 hashCode 方法。
*/
int hashCode();
}
可选操作
此接口中的 add、addAll、clear、remove、removeAll、retainAll 方法被 API 文档描述为可选操作,在当具体集合类有一些局限性时,如只读、只能删除等,需要抛出 UnsupportedOperationException 异常。
Core Java 中关于可选操作的说明:“这看起来与接口的概念有所抵触。确实,从理论的角度看,在这里给出的方法很难令人满意。” 但 “集合类库的设计者必须解决一组特别严格且又相互冲突的需求。用户希望类库应该易于学习,使用方便。” “要同时达到所有目标的要求,或者尽量兼顾所有目标完全是不可能的。”
Core Java 中关于可选操作的说明:“这看起来与接口的概念有所抵触。确实,从理论的角度看,在这里给出的方法很难令人满意。” 但 “集合类库的设计者必须解决一组特别严格且又相互冲突的需求。用户希望类库应该易于学习,使用方便。” “要同时达到所有目标的要求,或者尽量兼顾所有目标完全是不可能的。”
迭代器模式
Collection 接口继承自 Iterable 接口,是为了使用迭代器(Iterator)模式。迭代器模式又叫游标(Cursor)模式,是对象的行为模式。迭代器模式可以顺序地访问一个集合中的元素而不必暴露集合的内部表象。迭代器模式与集合框架是相辅相成的,之所以要在 JCF 中使用迭代器模式,是因为集合对象必须提供一个遍历集合中的所有元素的方法,以便获取或移除元素。而当遍历方式不变但需要改变具体集合实现类,或具体实现类不变但需要修改遍历方式时,为了符合“开-闭”原则,需要将访问集合元素的逻辑封装起来,使其独立于集合对象,于是使用了迭代器模式。这样,在进行迭代时,客户端无需知道集合的具体实现,而若需要改变迭代方式时,则只要使用新的迭代器对象即可。迭代器在客户端与集合之间增加了一个中介层,让客户端与集合的通信从直接变成间接,缓冲了客户端的变化对集合的影响,以及集合的变化对客户端的影响。
package java.lang;
import java.util.Iterator;
public interface Iterable<T> {
Iterator<T> iterator();
}
其定义了一个 iterator() 方法,这是一个工厂方法,实现类需重写此方法,返回在集合元素中进行迭代的迭代器对象。
任何实现了 Iterable 接口的类都可以使用 foreach 语法。
Iterator 接口源码如下:
package java.util;
public interface Iterator<E> {
/**
* 判断是否仍有元素可以迭代。
*/
boolean hasNext();
/**
* 返回迭代的下一个元素。
*/
E next();
/**
* 从迭代器指向的集合中移除迭代器返回的最后一个元素。
*/
void remove();
}
在 JCF 中,迭代器模式涉及到的角色如下:
抽象迭代器(Iterator)角色:如 java.util.Iterator
抽象集合(Aggregate)角色:如 java.util.Collection
具体迭代器(ConcreteIterator)角色:如 java.util.ArrayList.Itr
具体集合(ConcreteAggregate)角色:如 java.util.ArrayList
关于迭代器模式具体的实现和细节,后面写 ArrayList 的时候再详细说明。
AbstractCollection
JCF提供了一个实现了 Collection 接口的抽象类 AbstractCollection,其提供了 Collection 接口中一些方法的默认实现,以便子类继承使用。源码节选:public abstract class AbstractCollection<E> implements Collection<E> {
protected AbstractCollection() {
}
// ...
public boolean isEmpty() {
return size() == 0;
}
// ...
public boolean add(E e) {
// 若子类未实现可选方法,默认抛出 UnsupportedOperationException 异常.
throw new UnsupportedOperationException();
}
// ...
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
// ...
}
List
JCF 没有提供任何 Collection 接口的直接具体实现类,而是定义了子接口 List, Set, Queue,让具体集合类实现它们。List(列表)是有序的集合,允许重复元素。List 接口源码如下:
package java.util;
public interface List<E> extends Collection<E> {
/**
* 返回此列表中的元素个数。
*/
int size();
/**
* 判断此列表是否不包含元素。
*/
boolean isEmpty();
/**
* 判断此列表是否包含指定元素。
*/
boolean contains(Object o);
/**
* 迭代器。
*/
Iterator<E> iterator();
/**
* 返回按顺序包含此列表中所有元素的数组。
*/
Object[] toArray();
/**
* 返回按顺序包含此列表中所有元素的数组,并可指定返回数组的运行时类型。
*/
<T> T[] toArray(T[] a);
/**
* 在此列表的尾部添加指定元素。
*/
boolean add(E e);
/**
* 从此集合中移除第一次出现的指定元素。
*/
boolean remove(Object o);
/**
* 如果此列表包含指定集合中的所有元素,则返回 true。
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合中的所有元素都添加到此列表的结尾,顺序是指定集合的迭代器返回这些元素的顺序。
* 若此集合因此调用而发生改变则返回 true。
*/
boolean addAll(Collection<? extends E> c);
/**
* 将指定集合中的所有元素都插入到列表中的指定位置。
* 若此列表因此调用而发生改变则返回 true。
*/
boolean addAll(int index, Collection<? extends E> c);
/**
* 从此列表中移除那些也包含在指定集合中的所有元素。
*/
boolean removeAll(Collection<?> c);
/**
* 从此列表中移除那些未包含在指定集合中的所有元素。
*/
boolean retainAll(Collection<?> c);
/**
* 移除此列表中的所有元素。
*/
void clear();
boolean equals(Object o);
int hashCode();
/**
* 返回列表中指定位置的元素。
*/
E get(int index);
/**
* 用指定元素替换列表中指定位置的元素。
*/
E set(int index, E element);
/**
* 在此列表的指定位置插入指定元素。
* 将当前处于该位置的元素和所有后续元素向右移动。
*/
void add(int index, E element);
/**
* 从此集合中移除指定位置的元素。
*/
E remove(int index);
/**
* 返回此列表中第一次出现的指定元素的索引,若不包含则返回 -1。
*/
int indexOf(Object o);
/**
* 返回此列表中最后一次出现的指定元素的索引,若不包含则返回 -1。
*/
int lastIndexOf(Object o);
/**
* 列表迭代器。
*/
ListIterator<E> listIterator();
/**
* 列表迭代器,定义初始位置。
*/
ListIterator<E> listIterator(int index);
/**
* 返回此列表从指定位置 fromIndex(包括 )到指定位置 toIndex(不包括)之间的子列表。
*/
List<E> subList(int fromIndex, int toIndex);
做为 Collection 接口的扩展,List 接口强调了其有序性,增加了一些比较方便操作序列的方法。同样,也增加了一个返回 ListIterator 迭代器的工厂方法,此迭代器中增加了一些比如逆迭代等的其他方法,源码如下:
package java.util;
public interface ListIterator<E> extends Iterator<E> {
/**
* 以正向遍历列表时,判断是否仍有元素可以迭代。
*/
boolean hasNext();
/**
* 返回迭代的列表中的下一个元素。
*/
E next();
/**
* 以逆向遍历列表时,判断是否仍有元素可以迭代。
*/
boolean hasPrevious();
/**
* 返回迭代的列表中的前一个元素。
*/
E previous();
/**
* 返回对 next 的后续调用所返回元素的索引。
*/
int nextIndex();
/**
* 返回对 previous 的后续调用所返回元素的索引。
*/
int previousIndex();
/**
* 从迭代器指向的列表中移除迭代器返回的最后一个元素。
*/
void remove();
/**
* 用指定元素替换迭代器返回的最后一个元素。
*/
void set(E e);
/**
* 将指定的元素插入列表。
* 位置为迭代器 next 返回的下一个元素之前或 previous 返回的下一个元素之后。
*/
void add(E e);
}