java记录之AbstractCollection
AbstractCollection是实现Collection接口的抽象类
实现的方法
1.是否为空集合
直接通过判断size的大小是否为0
public boolean isEmpty() {
return size() == 0;
}
2.是否包含指定元素
支持元素为null,如果待判定元素和null==则视为包含,否则通过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;
}
3.生成Object数组
考虑到集合在遍历的时候可能会删除或者添加,所以需要for循环和迭代器配合操作,当我根据集合长度初次生成的新数组长度是不变的。
1)但是当元素已经减少的时候,i < r.length将不具备参考价值,而且可能带来数组越界风险,所以需要判断当前迭代器的下一个值是否存在,如果不存在,说明已经被其他同步操作影响导致元素减少,所以返回到当前位置的数组return Arrays.copyOf(r, i);
2)当被其他同步操作影响导致元素增加的时候,势必会超过之前r.length,所以for循环已经结束,但是还有元素没有被拷贝到数组,所以需要执行finishToArray(r, it),把多出来的拷贝进去。
return it.hasNext() ? finishToArray(r, it) : r;
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;
}
4.生成与传入类型相同的数组
(T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
根据类型生成同等类型的数组。下面是使用场景
List list = new ArrayList(size());
for (E e : this)
list.add(e);
return list.toArray(a);
和方法三思路相同,稍有不同的是在元素因某操作减少的时候
1)
if (a == r) {
r[i] = null; // 如果减少到两个数组一样,那就把新开辟的数组r元素置空,然后返回原数组。
}
2)如果给定的数组a长度还是不够放我现有的元素,那就返回新开辟数组r的当前位置的拷贝
3)如果给定的数组a长度是够的,那就把新开辟数组r到当前位置的拷贝再拷到给定数组a
如果给定数组a大小比元素的数量多了,那就把多出来的置为空
注:1),3)都是返回给定数组a(3是处理过的)
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;
}
5.转化成数组的收尾操作
就是为了把给定迭代器后来又增加的部分也拷贝到数组
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;
// overflow-conscious code
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
r = Arrays.copyOf(r, newCap);
}
r[i++] = (T)it.next();
}
// trim if overallocated
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
6.容量的处理
当容量大到位负数的时候,说明溢出了,会抛出OutOfMemoryError错误;
最大只能到Integer.MAX_VALUE
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}