AbstractList给List提供了一个骨架实现,它的声明是这样的:
public abstract class AbstractList extends AbstractCollection implements List
继承AbstractCollection,实现List接口。
有关AbstractCollection:http://blog.csdn.net/treeroot/archive/2004/09/11/101622.aspx
有关List: http://blog.csdn.net/treeroot/archive/2004/09/14/104638.aspx
下面来看一下该类中的方法
public boolean add(Object o) {
add(size(), o);
return true;
}
直接调用方法add(int index,Object o)在末尾插入一个数据
abstract public Object get(int index);
该方法未实现
public Object set(int index, Object element) {
throw new UnsupportedOperationException();
}
该方法不受支持
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
该方法不受支持,这个方法直接影响上面的public boolean add(Object o)方法。
public Object remove(int index) {
throw new UnsupportedOperationException();
}
该方法不受支持
public int indexOf(Object o) {
ListIterator e = listIterator();
if (o==null) {
while (e.hasNext())
if (e.next()==null)
return e.previousIndex();
} else {
while (e.hasNext())
if (o.equals(e.next()))
return e.previousIndex();
}
return -1;
}
该方法获得指定元素在列表中的索引,正向搜索,找到的是一个最小值。
找不到的话就返回-1,找不到的情况就要遍历整个列表。
public int lastIndexOf(Object o) {
ListIterator e = listIterator(size());
if (o==null) {
while (e.hasPrevious())
if (e.previous()==null)
return e.nextIndex();
} else {
while (e.hasPrevious())
if (o.equals(e.previous()))
return e.nextIndex();
}
return -1;
}
这个方法几乎和上面的是一样的,不过是从后面向前面找而已,找到的是一个索引的最大值。
public void clear() {
removeRange(0, size());
}
清楚两个索引之间的所有元素,包括开始,不包括结束,参见removeRange方法。
public boolean addAll(int index, Collection c) {
boolean modified = false;
Iterator e = c.iterator();
while (e.hasNext()) {
add(index++, e.next());
modified = true;
}
return modified;
}
这个方法通过循环调用add方法来实现,因为每次调用add方法都要完成元素的后移,所以一种需要移动
c.size()次,效率比较低下。子类中一般都会覆盖这个方法。
public Iterator iterator() {
return new Itr();
}
这里有一个内部类Itr,参见下面的定义。
public ListIterator listIterator() {
return listIterator(0);
}
返回默认的列表迭代器,起始位置在最前面。
public ListIterator listIterator(final int index) {
if (index<0 || index>size())
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
先检查越界情况,同样有一个内部类ListItr,参见下面的定义。
以下是Itr的定义:
有关Iterator接口:http://blog.csdn.net/treeroot/archive/2004/09/11/101589.aspx
私有的内部类
private class Itr implements Iterator {
int cursor = 0;
记录游标位置
int lastRet = -1;
最后一次调用next()或者previous()的索引,其实Iterator都没有定义previous()。
int expectedModCount = modCount;
记录修改次数,modCount在AbstractList中定义为结构话改变List的次数。
这里是为了在Iterator和ListIterotor访问List时出现并发访问,我们后面再讨论这个问题。
public boolean hasNext() {
return cursor != size();
}
如果当前游标不等于集合的大小(那么肯定0到size()-1中的一个值)说明还有下一个值。
size()是AbstractList中的方法。
public Object next() {
try {
Object next = get(cursor);
checkForComodification();
lastRet = cursor++;
return next;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
这里比较讨厌的是调用了AbstractList中的方法get(int index),这里捕捉了一个系统异常(可以不
捕捉的异常)IndexOutOfBoundsException。无论如何都先抛出并发访问异常ConcurrentModificationException
(如果有的话)。正常情况下当前游标和最后一次访问索引都加1。
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch(IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
如果最后一次访问的索引是-1(刚获得Iterator时就是这样的),抛出IllegalStateException异常。
否则就删除该元素,如果该元素在当前游标之前,游标值要前移。因为是Iterator改变了List的结构,
这里要修正expertedModCount值。这里如果删除的时候的时候越界,一定是其他地方在修改这个List,
所以抛出并发访问异常。注意:这里把lastRet设置为了-1,此时不能调用remove以及ListIterator中
的add,set方法了。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
如果两个地方记录的修改次数不一样,说明还有其他地方在修改这个List。
}
以下是ListItr的定义:
有关ListIterator接口:http://blog.csdn.net/treeroot/archive/2004/09/14/104608.aspx
内部私有类
private class ListItr extends Itr implements ListIterator {
ListItr(int index) {
cursor = index;
}
构造函数,初始化当前游标位置。
public boolean hasPrevious() {
return cursor != 0;
}
当前游标不为0表示前面有元素。
public Object previous() {
try {
int i = cursor - 1;
Object previous = get(i);
checkForComodification();
lastRet = cursor = i;
return previous;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
返回当前游标的前一个元素,游标值和最后一次访问索引都有改变,有关并发控制参考Itr
public int nextIndex() {
return cursor;
}
下一个元素的索引和当前游标相等。
public int previousIndex() {
return cursor-1;
}
不用多说
public void set(Object o) {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, o);
expectedModCount = modCount;
} catch(IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
调用外围类的set方法,并发控制参考Itr中remove方法的说明。
public void add(Object o) {
checkForComodification();
try {
AbstractList.this.add(cursor++, o);
lastRet = -1;
expectedModCount = modCount;
} catch(IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
参考Itr中remove方法的说明。
}
回到AbstractList的方法
public List subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList(this, fromIndex, toIndex) :
new SubList(this, fromIndex, toIndex));
}
如果该List实现了RandomAccess接口,返回一个新的RandomAccessSubList实例,
否则返回一个SubList实例,这两个类在后面定义。
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
while(e1.hasNext() && e2.hasNext()) {
Object o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
这个方法比较简洁,通过遍历两个列表来比较,只有两个列表的元素以及顺序完全一样才相等。
public int hashCode() {
int hashCode = 1;
Iterator i = iterator();
while (i.hasNext()) {
Object obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
return hashCode;
}
这种算法完全可以保证:两个List相等时他们的hashCode也相等。
protected void removeRange(int fromIndex, int toIndex) {
ListIterator it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
这里通过迭代器来删除指定的元素,而迭代器调用的是remove方法,所以这个方法的效率不高。
protected transient int modCount = 0;
这个域表示该List被修改的次数,目的是为了控制并发访问。
AbstractList的内容已经结束,但是我们还用到了两个类:RandomAccessList和SubList。
看看SubList的定义:
class SubList extends AbstractList {
private AbstractList l;
private int offset;
private int size;
private int expectedModCount;
SubList(AbstractList list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
expectedModCount = l.modCount;
}
public Object set(int index, Object element) {
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
public Object get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, Object element) {
if (index<0 || index>size)
throw new IndexOutOfBoundsException();
checkForComodification();
l.add(index+offset, element);
expectedModCount = l.modCount;
size++;
modCount++;
}
public Object remove(int index) {
rangeCheck(index);
checkForComodification();
Object result = l.remove(index+offset);
expectedModCount = l.modCount;
size--;
modCount++;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
l.removeRange(fromIndex+offset, toIndex+offset);
expectedModCount = l.modCount;
size -= (toIndex-fromIndex);
modCount++;
}
public boolean addAll(Collection c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection c){
if (index<0 || index>size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
l.addAll(offset+index, c);
expectedModCount = l.modCount;
size += cSize;
modCount++;
return true;
}
public Iterator iterator() {
return listIterator();
}
public ListIterator listIterator(final int index) {
checkForComodification();
if (index<0 || index>size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
return new ListIterator() {
private ListIterator i = l.listIterator(index+offset);
public boolean hasNext() {
return nextIndex() < size;
}
public Object next() {
if (hasNext())
return i.next();
else
throw new NoSuchElementException();
}
public boolean hasPrevious() {
return previousIndex() >= 0;
}
public Object previous() {
if (hasPrevious())
return i.previous();
else
throw new NoSuchElementException();
}
public int nextIndex() {
return i.nextIndex() - offset;
}
public int previousIndex() {
return i.previousIndex() - offset;
}
public void remove() {
i.remove();
expectedModCount = l.modCount;
size--;
modCount++;
}
public void set(Object o) {
i.set(o);
}
public void add(Object o) {
i.add(o);
expectedModCount = l.modCount;
size++;
modCount++;
}
};
}
public List subList(int fromIndex, int toIndex) {
return new SubList(this, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index<0 || index>=size)
throw new IndexOutOfBoundsException("Index: "+index+
",Size: "+size);
}
private void checkForComodification() {
if (l.modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
这个类继承AbstractList,基本上很好理解,不过有几点需要主要:
1.注意l.modCount,modCount,expectedModCount的区别,modCount是SubList继承过来的域
expectedModCount是SubList为防止并发访问新加的域,l.modCount当然好理解。
2.public ListIterator listIterator(final int index)方法中用了一个匿名类。
3.注意SubList的构造函数只有一个,需要带三个参数,而且SubList只是一个视图,修改SubList
也就等于修改了参数中的list。
最后是RandomAccessSubList
class RandomAccessSubList extends SubList implements RandomAccess {
RandomAccessSubList(AbstractList list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public List subList(int fromIndex, int toIndex) {
return new RandomAccessSubList(this, fromIndex, toIndex);
}
}
这个类没有什么实在的东西,不过是类型和SubList不一样而已(因为多了一个RandomAccess接口).
这里只是分析了这个类的实现,并没有评价这个类设计的好坏,不过我是比较讨厌嵌套类(特别是嵌套
类还能调用外围类的方法),另外SubList返回的是一个视图,而不是一个完全独立的List,这样到底好不好呢?