您的位置:首页 > 编程语言 > Java开发

Java AbstractCollection源码分析

2015-10-29 13:47 513 查看
<span style="font-size:14px;">public abstract class AbstractCollection<E> implements Collection<E> {
/**
* Sole constructor.  (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractCollection() {
}

// Query Operations

/**
* Returns an iterator over the elements contained in this collection.
*
* @return an iterator over the elements contained in this collection
*/
public abstract Iterator<E> iterator();

public abstract int size();

/**
* {@inheritDoc}
*
* <p>This implementation returns <tt>size() == 0</tt>.
*/
public boolean isEmpty() {
return size() == 0;
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over the elements in the collection,
* checking each element in turn for equality with the specified element.
*
* @throws ClassCastException   {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
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;
}

/**
* {@inheritDoc}
*
* <p>This implementation returns an array containing all the elements
* returned by this collection's iterator, in the same order, stored in
* consecutive elements of the array, starting with index {@code 0}.
* The length of the returned array is equal to the number of elements
* returned by the iterator, even if the size of this collection changes
* during iteration, as might happen if the collection permits
* concurrent modification during iteration.  The {@code size} method is
* called only as an optimization hint; the correct result is returned
* even if the iterator returns a different number of elements.
*
* <p>This method is equivalent to:
*
*  <pre> {@code
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
*     list.add(e);
* return list.toArray();
* }</pre>
*/
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;
}

/**
* {@inheritDoc}
*
* <p>This implementation returns an array containing all the elements
* returned by this collection's iterator in the same order, stored in
* consecutive elements of the array, starting with index {@code 0}.
* If the number of elements returned by the iterator is too large to
* fit into the specified array, then the elements are returned in a
* newly allocated array with length equal to the number of elements
* returned by the iterator, even if the size of this collection
* changes during iteration, as might happen if the collection permits
* concurrent modification during iteration.  The {@code size} method is
* called only as an optimization hint; the correct result is returned
* even if the iterator returns a different number of elements.
*
* <p>This method is equivalent to:
*
*  <pre> {@code
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
*     list.add(e);
* return list.toArray(a);
* }</pre>
*
* @throws ArrayStoreException  {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
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)
return Arrays.copyOf(r, i);
r[i] = null; // null-terminate
return r;
}
r[i] = (T)it.next();
}
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
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
* Reallocates the array being used within toArray when the iterator
* returned more elements than expected, and finishes filling it from
* the iterator.
*
* @param r the array, replete with previously stored elements
* @param it the in-progress iterator over this collection
* @return array containing the elements in the given array, plus any
*         further elements returned by the iterator, trimmed to size
*/
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);
}

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;
}

// Modification Operations

/**
* {@inheritDoc}
*
* <p>This implementation always throws an
* <tt>UnsupportedOperationException</tt>.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
* @throws IllegalArgumentException      {@inheritDoc}
* @throws IllegalStateException         {@inheritDoc}
*/
public boolean add(E e) {
throw new UnsupportedOperationException();
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over the collection looking for the
* specified element.  If it finds the element, it removes the element
* from the collection using the iterator's remove method.
*
* <p>Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's iterator method does not implement the <tt>remove</tt>
* method and this collection contains the specified object.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
*/
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;
}

// Bulk Operations

/**
* {@inheritDoc}
*
* <p>This implementation iterates over the specified collection,
* checking each element returned by the iterator in turn to see
* if it's contained in this collection.  If all elements are so
* contained <tt>true</tt> is returned, otherwise <tt>false</tt>.
*
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
* @see #contains(Object)
*/
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over the specified collection, and adds
* each object returned by the iterator to this collection, in turn.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is
* overridden (assuming the specified collection is non-empty).
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
* @throws IllegalArgumentException      {@inheritDoc}
* @throws IllegalStateException         {@inheritDoc}
*
* @see #add(Object)
*/
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over this collection, checking each
* element returned by the iterator in turn to see if it's contained
* in the specified collection.  If it's so contained, it's removed from
* this collection with the iterator's <tt>remove</tt> method.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> method
* and this collection contains one or more elements in common with the
* specified collection.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean removeAll(Collection<?> c) {
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over this collection, checking each
* element 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 <tt>remove</tt> method.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> method
* and this collection contains one or more elements not present in the
* specified collection.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean retainAll(Collection<?> c) {
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}

/**
* {@inheritDoc}
*
* <p>This implementation iterates over this collection, removing each
* element using the <tt>Iterator.remove</tt> operation.  Most
* implementations will probably choose to override this method for
* efficiency.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's <tt>iterator</tt> method does not implement the
* <tt>remove</tt> method and this collection is non-empty.
*
* @throws UnsupportedOperationException {@inheritDoc}
*/
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}

//  String conversion

/**
* Returns a string representation of this collection.  The string
* representation consists of a list of the collection's elements in the
* order they are returned by its iterator, enclosed in square brackets
* (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
* <tt>", "</tt> (comma and space).  Elements are converted to strings as
* by {@link String#valueOf(Object)}.
*
* @return 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(' ');
}
}

}
</span>


以上是Java JDK中的AbstractCollection源码,其中包括的功能函数有:

1,protected 的构造函数。

protected AbstractCollection() {
}


protected 修饰的类中属性和方法,可以在本类中使用,可以被其子类(即使不同包)使用,可以被同包中的其他类使用。

有个容易混淆的情况:

package 1;

class A{

protected int x;

}

package 2;

class B extends A{

x=2;//right

A a;

a.x;//wrong

}

注释:

Protected access requires a little more elaboration. Suppose class A declares a protected field x and is extended by a class B, which is defined in a different package (this last point is important). Class
B inherits the protected field x, and its code can access that field in the current instance of B or in any other instances of B that the code can refer to. This does not mean, however, that the code of class B can start reading the protected fields of arbitrary
instances of A! If an object is an instance of A but is not an instance of B, its fields are obviously not inherited by B, and the code of class B cannot read them.

更详细的信息参考:http://zhangjunhd.blog.51cto.com/113473/19287/

2,Iterator() & size()

public abstract Iterator<E> iterator();

public abstract int size();


虚拟函数,会在子孙类中实现。

3,isEmpty()

public boolean isEmpty() {
return size() == 0;
}
判断是否为空,是根据所含元素数量

4,Contains()

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<E> it=iterator();生成此collection的迭代器,进行collection的遍历。

在判断是否包含某个Object o的时候,分为此o==null?用等号判断相等;用元素所在类的equals()方法判断相等。所以若存入其中的元素是自定义对象,则需要重写其equals()方法。

5,toArray()

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;
}
这个集合类型和数组类型连接转化的”桥梁“。在function中,先按size()值创造Object 数组 r, 然后创建迭代器对collection进行遍历,依次复制collection的每一个元素到数组r中,直到collection遍历到了头,此时,数组r中全部包含了collection中的元素。这个时候,通过复制r数组创建一个新数组,返回。

最好,以防在运行期间,collection的大小改变了。则判断it.hasNext()来确定是否遇到数组r的大小变得小与collection的大小情况,若是,则运行finishToArray()进行重新复制,否则,返回r.

6,toArray()

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)
return Arrays.copyOf(r, i);
r[i] = null; // null-terminate
return r;
}
r[i] = (T)it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}


将collection的元素转化成array类型,并存放于T[] a中。

可见修饰符后的<T>是申明一个泛型T。函数的返回的值类型是T[]。

创建临时数组T[] r ,若指定数组a的大小大于等于collection的大小,则r 等于a;否则,a太小了,按照collection的大小重新创建数组给r。

若r没到最末,依次复制collection 元素到r中,直到collection到末尾。若r是新创建的数组即不等于a,则返回的是以r为模板创建的新数组;若r就是a则加上数组结束符号,返回r.(这里不知道解读可对,也不知为什么这样设计)

同样,也要考虑运行期间,万一collection的大小改变的情况。

7,finishToArray()

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;


设定array最大能存储的size大小。具体为啥这样计算不是很清楚

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);
}


第一次,是i==cap ,进行扩大r的容量的操作,首先尝试夸1.5倍左右,然后判断是否超过了数组的最大容量限度。若超过,真通过hugeCapacity再次计算。

扩大r的容量后,开始依次复制collection的元素到数组里了。

最后返回r,此时r中的元素都是collection中的元素,否则r中有填充元素,则截取r中前i个元素,新建数组返回。

8,hugeCapacity()

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;
}
重新调整最大容量

9,remove()

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;
}


remove删除collection中的一个object,首先分object是不是null,null通过==来判断相等,否则通过equals来判断内容相等。

10,containsAll()

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

判断是否包含 collection e 中的所有元素。<?>为泛型通配符,在宣告名称时如果指定了<?>而 不使用"extends",则预设是允许Object及其下的子类,也就是所有的Java对象了,那为什么不直接使用GenericFoo宣告就好了,何 必要用GenericFoo<?>来宣告?使用通配字符有点要注意的是,透过使用通配字符宣告的名称所参考的对象,您没办法再对它加入新的资 讯,您只能取得它的信息或是移除它的信息,关于泛型通配符的使用参考 http://www.iteedu.com/plang/java/javadiary/70.php 还不清楚此知识点,有待进一步学习

11,AddAll()

public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}


将一个新的collection c全部写到原collection中,只要原collection有状态改变,即返回true.增加成功与否,还要依赖add的具体实现,

12,removeAll()

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


从原collection中删除c中的元素,通过contains元素来判断c中是否存在某个元素,是的话,从原collection中删除该元素。

13,retainAll()

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

只保留即在c中也在原collection中的元素。方法和removeAll()相似,只是在判断条件上,删除的是不在c的元素。

14,clear()

public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}


通过迭代器,依次遍历collection中元素,依次删除。

15,toString()

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(' ');
}
}


返回这个collection的string表现形式,会将元素放到【】中,通过逗号“,”区分各元素。但是为什么会有个e==this的判断,还不清楚。

若有不对之处,希望得到你的指导更正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: