java的AbstractList源码分析

 
关键词 AbstractList源码分                                          
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 ,这样到底好不好呢?
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值