Java集合框架源码阅读之AbstractCollection

Posted sanxiandoupi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合框架源码阅读之AbstractCollection相关的知识,希望对你有一定的参考价值。

AbstractCollection是集合实现类的根抽象实现类,它实现了Collection接口,集合中的三个分支SetListQueue都是继承此类之后再进行各自实现的扩展,分别是AbstractSetAbstractListAbstractQueue。这三个分支有一些共同之处,需要用一些共同的方法,因此出现了AbstractCollection类,它包含了一些这三个分支都会用到的常用方法。而这三个分支也各有抽象类,因为这三个分支下面的一些具体实现也会有一些当前分支通用的方法,因此也给每个分支设计了抽象方法用来继承。

AbstractCollection方法基本上可以分为下面几种:

  • 增:add()、addAll()
  • 删:remove()、removeAll()、clear()
  • 查:size()、isEmpty()、contains()、contailsAll()、retainAll()
  • 转:iterator()、toArray()、finishToArray()、hugeCapacity()、toString()

AbstractCollection

源码如下:

public abstract class <E> implements Collection<E> {

protect () {}
public abstract Iterator<E> iterator();
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
/* 判断是否包含某个对象,这个函数肯定是可以通用的,所以直接在抽象类里面实现了,
这里都是把 null 和不为 null 的值分开处理的,在后面也可以看到很多这种情况,
主要是考虑到 o.equals()会抛 nullpoint 异常。但是为什么不使用 it.next().equals(o)
来代替呢?因为列表里是有可能存一个 null 的值的,比如[1, 2, 3, null, 5, 6],这时候
使用 it.next().equals(o) 依然会出现 nullpoint */
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;
}

/* 返回一个包含了这个集合中所有元素的数组,数组中元素的顺序和集合中元素的顺序相同。,
即使在迭代的过程中数组的长度被扩充(当集合被几个线程并行修改的时候,长度是非常有可能会被扩充的),最终返回的数组的长度与 iterator 中元素的个数相同。
如果集合中的元素比预期的少,则调用 Arrays.copyOf() 方法将数组的元素复制到新数组中,并返回新数组
如果集合中的元素比渔区的多,在调用 finishToArray() 方法生成新的数组,并返回新数组
*/
public Object[] toArray() {
// 这里调用 size() 方法只是对这个数组的长度做一个预估,实际上有可能会被自动扩充
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;
}
/* 数组可以扩容的最大值,实际上在Java中,数组的最大长度是 Integer.MAX_VALUE-2,
为了防止内存溢出,在这里就做了 Integer.MAX_VALUE-8 这样的一个限制
关于为什么最大长度要减去 8,Java官方的解释是:对于有些虚拟机实现来说,数组对象的头部会占用这 8 个字节 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/* 给数组扩容 */
("unchecked")
private static <T> T[] finishArray(T[] r, Iterator<?> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
// 当数组索引指向最后一个元素时,对数组进行扩容,扩容大小:cap + cap/2 + 1
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();
}
return (i == r.length) ? r : Arrays.cofyOf(r, i);
}
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;
}

/* 返回指定类型的数组 */
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()) {
// 如果数组时参数中的数组,则将剩余部分的值都设置为 null
if (a == r) {
r[i] = null;
} else if (a.length < i) {
// 如果传入的数组长度小余集合,则通过 Arrays.copyOf 将之前数组中的元素复制到新数组中
return Arrays.copyOf(r, i);
} else {
// 如果传入数组的长度比集合大,则将多的元素设置为 null
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T) it.next()
}
return it.hasNext() ? finishToArray(r, it) : r;
}

// Collection 不支持 add 操作
public boolean add(E e) {
throw new UnsupportedOperationException();
}
// 删除元素,这里 null 值依旧需要特殊处理,因为有 o.equals()
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;
}

public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}


// this implementation iterates over the specified collection, and adds each
// object returned by the iterator to this colection, in return
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
if (E e : c)
if (add(e))
modified = true;
return modified;
}

public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}

// This implementation iterates over this collection, checking each elements returned
// by the iterator in turn to see if it's contained in the specified collection.
// if it's not so contained, it's removed from this collection with the iterator's remove method
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (! c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
// 删除集合里的所有元素
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}

// Returns a string representation of this collection.
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(' ');
}
}
}

原文:大专栏  Java集合框架源码阅读之AbstractCollection


以上是关于Java集合框架源码阅读之AbstractCollection的主要内容,如果未能解决你的问题,请参考以下文章

jdk源码阅读笔记之java集合框架(ArrayList)

jdk源码阅读笔记之java集合框架(LinkedList)

如果天空不是集合框架阅读列表整理

java集合框架源码剖析系列java源码剖析之TreeMap

源码阅读Java集合 - ArrayList深度源码解读

java源码分析之集合框架HashMap 10