AbstractList
给
List
提供了一个骨架实现,它的声明是这样的:
public abstract class AbstractList extends AbstractCollection implements List
继承 AbstractCollection ,实现 List 接口。
有关 AbstractCollection : http://blog.youkuaiyun.com/treeroot/archive/2004/09/11/101622.aspx
有关 List : http://blog.youkuaiyun.com/treeroot/archive/2004/09/14/104638.aspx
public abstract class AbstractList extends AbstractCollection implements List
继承 AbstractCollection ,实现 List 接口。
有关 AbstractCollection : http://blog.youkuaiyun.com/treeroot/archive/2004/09/11/101622.aspx
有关 List : http://blog.youkuaiyun.com/treeroot/archive/2004/09/14/104638.aspx
下面来看一下该类中的方法
public boolean add(Object o) {
add(size(), o);
return true;
}
直接调用方法 add(int index,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();
}
该方法不受支持
throw new UnsupportedOperationException();
}
该方法不受支持
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
该方法不受支持,这个方法直接影响上面的 public boolean add(Object o) 方法。
throw new UnsupportedOperationException();
}
该方法不受支持,这个方法直接影响上面的 public boolean add(Object o) 方法。
public Object remove(int index) {
throw new UnsupportedOperationException();
}
该方法不受支持
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 ,找不到的情况就要遍历整个列表。
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;
}
这个方法几乎和上面的是一样的,不过是从后面向前面找而已,找到的是一个索引的最大值。
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 方法。
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() 次,效率比较低下。子类中一般都会覆盖这个方法。
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, 参见下面的定义。
return new Itr();
}
这里有一个内部类 Itr, 参见下面的定义。
public ListIterator listIterator() {
return listIterator(0);
}
返回默认的列表迭代器,起始位置在最前面。
return listIterator(0);
}
返回默认的列表迭代器,起始位置在最前面。
public ListIterator listIterator(final int index) {
if (index<0 || index>size())
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
先检查越界情况,同样有一个内部类 ListItr ,参见下面的定义。
if (index<0 || index>size())
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
先检查越界情况,同样有一个内部类 ListItr ,参见下面的定义。
私有的内部类
private class Itr implements Iterator {
int cursor = 0;
记录游标位置
private class Itr implements Iterator {
int cursor = 0;
记录游标位置
int lastRet = -1;
最后一次调用 next() 或者 previous() 的索引,其实 Iterator 都没有定义 previous() 。
最后一次调用 next() 或者 previous() 的索引,其实 Iterator 都没有定义 previous() 。
int expectedModCount = modCount;
记录修改次数, modCount 在 AbstractList 中定义为结构话改变 List 的次数。
这里是为了在 Iterator 和 ListIterotor 访问 List 时出现并发访问,我们后面再讨论这个问题。
记录修改次数, modCount 在 AbstractList 中定义为结构话改变 List 的次数。
这里是为了在 Iterator 和 ListIterotor 访问 List 时出现并发访问,我们后面再讨论这个问题。
public boolean hasNext() {
return cursor != size();
}
如果当前游标不等于集合的大小 ( 那么肯定0到 size()-1 中的一个值 ) 说明还有下一个值。
size() 是 AbstractList 中的方法。
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 。
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 方法了。
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 。
}
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
如果两个地方记录的修改次数不一样,说明还有其他地方在修改这个 List 。
}
以下是
ListItr
的定义:
有关 ListIterator 接口 :http://blog.youkuaiyun.com/treeroot/archive/2004/09/14/104608.aspx
有关 ListIterator 接口 :http://blog.youkuaiyun.com/treeroot/archive/2004/09/14/104608.aspx
内部私有类
private class ListItr extends Itr implements ListIterator {
ListItr(int index) {
cursor = index;
}
构造函数,初始化当前游标位置。
private class ListItr extends Itr implements ListIterator {
ListItr(int index) {
cursor = index;
}
构造函数,初始化当前游标位置。
public boolean hasPrevious() {
return cursor != 0;
}
当前游标不为0表示前面有元素
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
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;
}
下一个元素的索引和当前游标相等。
return cursor;
}
下一个元素的索引和当前游标相等。
public int previousIndex() {
return cursor-1;
}
不用多说
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 方法的说明。
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 方法的说明。
}
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 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;
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());
}
这个方法比较简洁,通过遍历两个列表来比较 , 只有两个列表的元素以及顺序完全一样才相等。
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 也相等。
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 方法,所以这个方法的效率不高。
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 被修改的次数,目的是为了控制并发访问。
这个域表示该 List 被修改的次数,目的是为了控制并发访问。
AbstractList
的内容已经结束,但是我们还用到了两个类:
RandomAccessList
和
SubList
。
看看 SubList 的定义:
class SubList extends AbstractList {
private AbstractList l;
private int offset;
private int size;
private int expectedModCount;
看看 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;
}
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);
}
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
public Object get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
public int size() {
checkForComodification();
return 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++;
}
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;
}
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++;
}
checkForComodification();
l.removeRange(fromIndex+offset, toIndex+offset);
expectedModCount = l.modCount;
size -= (toIndex-fromIndex);
modCount++;
}
public boolean addAll(Collection c) {
return addAll(size, 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;
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;
}
l.addAll(offset+index, c);
expectedModCount = l.modCount;
size += cSize;
modCount++;
return true;
}
public Iterator iterator() {
return listIterator();
}
return listIterator();
}
public ListIterator listIterator(final int index) {
checkForComodification();
if (index<0 || index>size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
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++;
}
};
}
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);
}
return new SubList(this, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index<0 || index>=size)
throw new IndexOutOfBoundsException("Index: "+index+
",Size: "+size);
}
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 。
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);
}
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 接口 ).
return new RandomAccessSubList(this, fromIndex, toIndex);
}
}
这个类没有什么实在的东西,不过是类型和 SubList 不一样而已 ( 因为多了一个 RandomAccess 接口 ).
这里只是分析了这个类的实现,并没有评价这个类设计的好坏,不过我是比较讨厌嵌套类 ( 特别是嵌套
类还能调用外围类的方法 ), 另外 SubList 返回的是一个视图,而不是一个完全独立的 List ,这样到底好不好呢?