分享
 
 
 

AbstractList源码分析

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有