1. 概述
我们首先看一下Collection接口的javadoc,之后看一下在AbstractCollection中的实现。
2. Collection接口
下面是Collection中定义的接口列表,其中equals和hashCode是继承自Object,iterator方法是继承自Iterable,我们已经分析过,传送门:[集合类] 源码解析2(Iterator的实现)
下面是Collection接口,我们主要看一下接口方法注释。
public interface Collection<E> extends Iterable<E> {
/*************************查询操作******************************/
/**
* 返回集合的元素数量,最大是Integer.MAX_VALUE
*/
int size();
/**
* list没有元素,则返回true
*/
boolean isEmpty();
/**
* 如果在list中至少存在一个e,满足(o==null ? e==null : o.equals(e)),则返回true
* @throws ClassCastException 如果集合不接受指定元素的类型
* @throws NullPointerException 如果特定元素是null,而集合不接受null
*/
boolean contains(Object o);
/**
* 返回一个迭代器
*/
Iterator<E> iterator();
/**
* 按照一定顺序返回一个包含所有元素的数组,返回Object数组(范型会在编译期擦除),修改数组不会影响集合。
* 是基于数组和基于集合之间的api之间的桥梁
*/
Object[] toArray();
/**
* 返回一个包含所有元素的数组,保存到指定数组,返回数组的运行时类型是指定数组的运行时类型。
* 如果数组length小于集合数量,则按照指定类型和该集合的大小分配新数组。
* 如果数组length大于集合数量,则将剩余空闲元素设为null
*
* 如果集合保证迭代器返回元素顺序,这个方法必须以相同的顺序返回元素
* 是基于数组和基于集合之间的api之间的桥梁,并且可以控制返回数组的运行时类型,在某些情况下可以节省分配成本
* (猜想应该是如果要在数组后面追加内容,则可以直接分配最后需要的空间大小,否则第一次分配的空间则面临回收)
*
* 集合转数组demo:
* String[] y = x.toArray(new String[0]);
*
* @throws ArrayStoreException 如果指定数组的运行时类型不是集合中每一个元素的父类型
* @throws NullPointerException 如果指定数组是null
*/
<T> T[] toArray(T[] a);
/*************************修改操作******************************/
/**
* 添加成功,返回true
* 如果集合拒绝添加一个元素,必须抛出异常,而不是返回false
* @throws UnsupportedOperationException 当前的集合不支持add操作
* @throws ClassCastException 指定元素的类阻止将其添加到此集合中
* @throws NullPointerException 指定元素为null,并且集合不允许null元素
* @throws IllegalArgumentException 元素的某些属性阻止它被添加到这个集合中
* @throws IllegalStateException 由于插入限制,此时不能添加元素
*/
boolean add(E e);
/**
* 如果集合存在任意一个e,对于o满足 (o==null ? e==null : o.equals(e),则移除e
* 如果集合更改,返回true
* @throws ClassCastException 如果集合不接受指定元素的类型
* @throws NullPointerException 指定元素为null,并且集合不允许null元素
* @throws UnsupportedOperationException 当前的集合不支持remove操作
*/
boolean remove(Object o);
/*************************批量操作******************************/
/**
* 如果集合包含所有指定元素返回true
* @throws ClassCastException 如果集合不接受指定元素的类型
* @throws NullPointerException 指定集合包含null,并且集合不允许null元素
*/
boolean containsAll(Collection<?> c);
/**
* 将指定集合的所有元素添加到此集合,在操作中不能修改指定结合
* @throws UnsupportedOperationException 当前的集合不支持addAll操作
* @throws ClassCastException 指定集合中元素的类阻止将其添加到此集合中
* @throws NullPointerException 指定集合包含null,并且集合不允许null元素
* @throws IllegalArgumentException 如果集合中元素的某些属性阻止将其添加到此集合中
* @throws IllegalStateException 由于插入限制,不是所有元素都可以在此时添加
*/
boolean addAll(Collection<? extends E> c);
/**
* 删除此集合中包含指定集合的所有元素
* @throws UnsupportedOperationException 当前的集合不支持removeAll操作
* @throws ClassCastException 如果集合不接受指定元素的类型
* @throws NullPointerException 指定集合包含null,并且集合不允许null元素
*/
boolean removeAll(Collection<?> c);
/**
* 删除此集合中给定谓词的所有元素。迭代期间由谓词抛出的错误或运行时异常将传递给调用者。
*
* 实现要求:
* 默认实现使用其iterator()遍历集合的所有元素。使用Iterator.remove()删除每个匹配的元素。
* 如果集合的迭代器不支持删除,则将在第一个匹配的元素上抛出UnsupportedOperationException。
* @param filter 对于要删除的元素,返回true的谓词
* @return 如果任一元素被删除,返回true
* @throws NullPointerException 如果指定过滤器为null
* @throws UnsupportedOperationException 如果无法从该集合中删除元素
* 如果无法删除匹配的元素,或者通常不支持删除,则实现可能会抛出此异常
* @since 1.8
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
/**
* 从此集合中删除指定集合中不包含的所有元素
* 集合改变,返回true
* @throws UnsupportedOperationException 当前集合不支持retainAll操作
* @throws ClassCastException 至少一个元素的类型与指定集合不兼容(可选)
* @throws NullPointerException 当前集合存在至少一个null元素,并且指定元素不支持null
*/
boolean retainAll(Collection<?> c);
/**
* 移除集合中所有元素,方法返回后集合为空
* @throws UnsupportedOperationException 当前的集合不支持clear操作
*/
void clear();
/*************************比较和散列******************************/
/**
* 将指定的对象与此集合进行相等性比较。
* 集合接口没有对Object.equal的通用契约添加任何规定
* “直接”实现集合接口的程序员必须考虑是否选择重写Object.equals。
* 最简单的方法是依赖对象的实现,实现者可能希望实现一个“值比较”来代替默认的“引用比较”。
*
* 该方法的一般约定规定,等号必须是对称的
* List.equal方法和Set.equal方法的契约中,List只与其他List相等,而Set与其他Set相等。
*/
boolean equals(Object o);
/**
* 返回当前集合的hash码
* 虽然Collection接口没有对方法的通用契约添加任何规定
* 但程序员应该注意,任何覆盖equals方法的类也必须覆盖hashCode方法,以满足hashCode的通用契约。
* 特别是 c1.equals(c2) 意味着 c1.hashCode()==c2.hashCode()
*/
int hashCode();
/**
* stream方法,暂时不管
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
/**
* stream方法,暂时不管
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* stream方法,暂时不管
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
3. AbstractCollection
AbstractCollection我们主要看一下方法实现
public abstract class AbstractCollection<E> implements Collection<E> {
// 唯一的构造函数,通常提供给子类调用
protected AbstractCollection() {
}
// 两个抽象方法
public abstract Iterator<E> iterator();
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
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;
}
public Object[] toArray() {
// 这里的size只是估计值
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext())
// i还在循环,但是迭代器却没有下一个元素了,说明有并发remove操作,返回数组副本
return Arrays.copyOf(r, i);
r[i] = it.next();
}
// i遍历结束,迭代器还有下一个,说明有并发add操作,扩容,并将剩余元素添加到数组中
// 否则,返回数组
return it.hasNext() ? finishToArray(r, it) : r;
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
// 判断a的大小,不满足则利用反射创建新数组
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
// i还在循环,但是迭代器却没有下一个元素了,说明有并发remove操作
if (! it.hasNext()) {
// 如果没有创建新数组,最后一个元素置null,返回a
if (a == r) {
r[i] = null; // null-terminate
// 如果创建了新数组,并且当前数组长度大于a的长度,返回当前数组副本
} else if (a.length < i) {
return Arrays.copyOf(r, i);
// 如果创建了新数组,并且当前数组长度小于a的长度,将当前数组拷贝给a
} else {
System.arraycopy(r, 0, a, 0, i);
// 如果a数组没有用完,最后一个元素置null,返回a
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// i遍历结束,迭代器还有下一个,说明有并发add操作,扩容,并将剩余元素添加到数组中
// 否则,返回数组
return it.hasNext() ? finishToArray(r, it) : r;
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
// 最大数组数量 为 Integer.MAX_VALUE - 8
// 有的虚拟机实现,数组对象的头部会占用这8个字节
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 扩容,并将迭代器剩余元素添加到数组中
@SuppressWarnings("unchecked")
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
// 当前数组索引,从数组尾开始
int i = r.length;
while (it.hasNext()) {
// cap为数组长度
int cap = r.length;
// 当前数组索引等于数组长度,扩容
if (i == cap) {
// 扩容大小 newCap = cap * 1.5 + 1
int newCap = cap + (cap >> 1) + 1;
// 保证数组最大长度
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
// 扩容
r = Arrays.copyOf(r, newCap);
}
// 迭代,添加到数组中
r[i++] = (T)it.next();
}
// 如果当前索引等于数组长度,说明数组刚好用完,返回数组。否则,按照当前长度返回数组副本
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
// 求数组最大长度
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
// 如果没超过MAX_ARRAY_SIZE,就是MAX_ARRAY_SIZE
// 超过MAX_ARRAY_SIZE,最大是Integer.MAX_VALUE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
// 通过Collection接口注释中已经说明UnsupportedOperationException
// 说明AbstractCollection不支持add方法
public boolean add(E e) {
throw new UnsupportedOperationException();
}
// 移除o
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;
}
// 如果此集合中包含c中所有元素,返回true
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
// 添加c中元素到此集合中
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
// 如果此集合改变,返回true
return modified;
}
// 对比retainAll,删除c中含有的元素
public boolean removeAll(Collection<?> c) {
// 首先判断c不为空
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
// 如果此集合改变,返回true
return modified;
}
// 删除c中没有的元素
public boolean retainAll(Collection<?> c) {
// 首先判断c不为空
Objects.requireNonNull(c);
// 标志
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
// 使用contains方法,使用迭代器遍历此集合中的元素,如果c中不存在,删除
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
// 如果此集合改变,返回true
return modified;
}
// 使用迭代器remove所有元素
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
// 使用StringBuilder
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
// 当集合中添加了集合本身作为元素,会打印(this Collection)
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}