先来一张Collection类的“全家福”,方便大家理解类与类之间的关系:
(集合类库UML图来自于http://blog.youkuaiyun.com/vking_wang/article/details/16965853)
从图上可以看出来,集合大概可以分成2部分,一部分用Collection作为跟接口,另一部分用Map作为根接口。
我们先了解下Collection接口,Collection接口有方法(在1.8中新加入Stream方法,不作介绍):
可以注意到,接口中有一部分可选方法:add相关方法,clear,remove相关方法,retainAll方法。这些方法都会引起Collection结构发生改变。
Collection接口中给出了removeIf方法的默认实现:
default boolean removeIf(Predicate<? super E> filter) {//给removeIf方法传递一个lambda表达式,表达式的内容为Predicate中test方法的实现
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;
}
下面我们来看看Collection的抽象子类AbstractCollection,AbstractCollection是java自己提供的一个最基本的Collection的实现。当然它依然是一个抽象类。对于一个不可更改的集合,只要继承这个类并且实现迭代器和size()方法就行。
在此抽象类中,提供了一部分集合操作的通用实现,我们就来看看这些通用实现的其中两个:
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); //集合中的对象数目少于Size()的数目
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r; //集合中的对象数目比Size()多时进入finishToArray方法,集合中对象数目与size
}
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
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++) {
if (! it.hasNext()) { // fewer elements than expected
if (a == r) {
r[i] = null; // null-terminate
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
toArray无参方法返回一个Object数组,它的思路如下:
1.创建一个估算的大小Object数组,并初始化一个迭代器
2.当集合中元素数量小于数组长度时,复制集合元素到数组并截断数组,最后返回数组。
3.当集合中元素数量大于数组长度时,创建更大的数组并复制集合元素,最后返回数组。
toArray泛型参数方法返回数组的运行时类型与指定数组的运行时类型相同,它的思路如下:
1.创建一个“大”数组(当输入数组长度大时就是输入数组,当size方法大时就创建新数组)。
2.当集合中的元素比创建的数组中的元素少,且输入数组长度“大“时,将集合元素放在数组中,并给集合元素后面的数组元素赋值为null;
3.当集合中的元素比创建的数组中的元素少且比传入的数组长度多时,将集合元素放在数组中,并截断数组返回。
4.当集合中的元素比创建的数组中的元素少且比传入的数组长度少时,将集合元素放在数组中,将数组复制给输入数组,输入数组的其余值为null,并返回。
5.当集合中的元素比创建的数组中的元素多时,用finishToArray方法,创建更大的数组并返回。