今天我们来学习util包下的内容,collection作为根接口,继承自lang包下的Iterable,虽然同属集合,但Map与之无关。
1.结构
*它的子接口和实现类很多
- colltion下定义了很多的方法,具体如下,方法的用途就不说都能够见名知意,每个方法的具体实现也不一样,太多了。
2实现类AbstractCollection,
该实现类的结构如下
(1)方法定义
第一个是proected修饰的构造器,提供子类实现,然后定义了int型的size和迭代器的抽象方法。
isEmpty方法,判断是否为空,如果size==0的话就返回true,反之。
public boolean isEmpty() {
return size() == 0;
}
contains方法,用来判断集合中是否包含传入的对象,当且仅当此 collection 包含至少一个满足 (o==null ? e==null :o.equals(e)) 的元素 e 时,返回 true
,
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;
}
toArray()方法,可以直接将collection类型转化为数组类型
,先根据集合大小估计数组长度,然后对集合元素进行迭代,并将集合中的元素copy到数组中,如果长度不够的话就调用该类中的finishToArray方法,若估算的长度够直接返回该数组。
public Object[] toArray() {
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext())
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
它还有一个重载的方法,其返回数组的运行时类型与指定数组的运行时类型相同,实现机制就是用到反射。
public <T> T[] toArray(T[] a) {
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()) {
if (a != r)
return Arrays.copyOf(r, i);
r[i] = null;
return r;
}
r[i] = (T)it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
接下来定义了一个常量,至于为什么要-8,源码中注释是”虚拟机在数组中保留一些标题字。分配较大的阵列可能发生OutOfMemoryError:数组大小超过VM的限制”
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
接下来是 finishToArray(T[] r, Iterator
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
if (i == cap) {
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);
}
接下来是hugeCapacity(int minCapacity)方法,传入int的参数,若小于零,抛出内存溢出的错误,然后看其是否大于Integer.MAX_VALUE - 8;确定返回值
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
然后定义一个add(E e)方法,该方法不做任何操作,就是抛出异常,通过子类重写定义。
public boolean add(E e) {
throw new UnsupportedOperationException();
}
remove(Object o)方法
addAll(),removeAll都是增强版的
containsAll(Collection
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
clear()方法就是清空集合
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
最后一个toString(),如果集合为空,返回[ ]这玩意,经常看到,不为空情况,创建一个StringBuilder对象,与String的区别就是长度可变。添加一个[ 接着向里面一个内容,在添加一个,和空格,完成之后添加]
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
对本人亲自测试如下
public static void main(String[] args) {
Collection c=new ArrayList();
c.add("111");
c.add("222");
System.out.println(c.toString());
}
打印结果:[111, 222]