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,这样到底好不好呢?

|