关于java集合框架中AbstractSequentialList类的理解

LinkedList是AbstractSequentialList的子类,而ArrayList是AbstractList的子类,AbstractSequentialList也是AbstractList的子类。

AbstractSequentialList的API文档

这个类提供了一个基本的List接口实现,为实现序列访问的数据储存结构的提供了所需要的最小化的接口实现。对于支持随机访问数据的List比如数组,应该优先使用AbstractList

这里是与随机访问类AbstractList类中相对的另一套系统,采用的是在迭代器的基础上实现的get、set、add和remove方法

为了实现这个列表。仅仅需要拓展这个类,并且提供ListIterator和size方法。 
对于不可修改的List,编程人员只需要实现Iterator的hasNext、next和hasPrevious、previous和index方法 
对于可修改的List还需要额外实现Iterator的的set的方法 
对于大小可变的List,还需要额外的实现Iterator的remove和add方法


AbstractSequentiaList和RandomAccess主要的区别是AbstractSequentiaList的主要方法都是通过迭代器实现的。而不是直接实现的(不通过迭代器,比如ArrayList实现的方式是通过数组实现的。)因此对于一些可以提供RandomAccess的方法,直接使用方法可能更快。因为迭代器移动需要一定代价。

源码分析

AbstractSequentialList方法的实现并没有特别需要注意的地方。主要是因为由于大部分的方法均是通过listIterator(int)的方法实现。但是listIterator(int)方法是一个抽象方法,基本实现只能从LinkedList中分析。 
这里简单的分析一些编程技巧。

 1 public E set(int index, E element) {
 2         try {
 3             ListIterator<E> e = listIterator(index);
 4             E oldVal = e.next();
 5             e.set(element);
 6             return oldVal;
 7         } catch (NoSuchElementException exc) {
 8             throw new IndexOutOfBoundsException("Index: "+index);
 9         }
10     }
11     public E remove(int index) {
12         try {
13             ListIterator<E> e = listIterator(index);
14             E outCast = e.next();
15             e.remove();
16             return outCast;
17         } catch (NoSuchElementException exc) {
18             throw new IndexOutOfBoundsException("Index: "+index);
19         }
20     }

set和remove方法返回了之前的oldVal,这样可以用于一些其他的操作。

 1 public boolean addAll(int index, Collection<? extends E> c) {
 2         try {
 3             boolean modified = false;
 4             ListIterator<E> e1 = listIterator(index);
 5             Iterator<? extends E> e2 = c.iterator();
 6             while (e2.hasNext()) {
 7                 e1.add(e2.next());
 8                 modified = true;
 9             }
10             return modified;
11         } catch (NoSuchElementException exc) {
12             throw new IndexOutOfBoundsException("Index: "+index);
13         }
14     }

首先代码很清晰。只需要说明三点: 
一个问题是迭代器e2并不是要求是ListIterator,而仅仅是Iterator。换句话说并不对容器类型做要求。这也是利用了迭代器的优点之一。 
第二个问题是这里设定了一个modified的变量。用来表示原表是否被更改。这样即使更改失败了,也可以通过返回值来判断是否对原进行了修改。

1 ListIterator<E> e1 = listIterator(index);
2 Iterator<? extends E> e2 = c.iterator();

第三个问题是通用的问题,首先是这里所有的方法都采用了这样的结构

1 try {
2 } catch (NoSuchElementException exc) {
3       throw new IndexOutOfBoundsException("Index: "+index);
4 }

这里将一个RuntimeException的未检查错误转换成了一个检查错误IndexOutOfBoundsException然后抛出。根据我目前查到的解释。大部分是说这样做是为了帮助将编程人员更好的定位问题。

posted @ 2017-04-04 16:41  夏威夷8080  阅读(790)  评论(0)    收藏  举报