转载请注明出处:http://blog.csdn.net/mazhimazh/article/details/17759579
List是我们在项目开发中常用的集合,List集合的特性如下:
集合中的元素有序(保持添加元素的顺序)、内部的数据可以重复。
说明一下:
null值可以有多个。举个例子,如List接口的实现类ArrayList,其底层的实现是一个数组,定义如下:
- private transient Object[] elementData;
下面来介绍一下List集合所依赖的接口及抽象类
1、List接口
查找集合框架图后可知,具体的List实现类如ArrayList、Linked等继承了AbstractCollection抽象类并且实现了List接口。List接口的定义如下:
- public interface List<E> extends Collection<E> {
- // Query Operations
- int size();
- boolean isEmpty();
- boolean contains(Object o);
- Iterator<E> iterator();
- Object[] toArray();
- <T> T[] toArray(T[] a);
- // Modification Operations
- boolean add(E e);
- boolean remove(Object o);
- // Bulk Modification Operations
- boolean containsAll(Collection<?> c);
- boolean addAll(Collection<? extends E> c);
- boolean addAll(int index, Collection<? extends E> c);
- boolean removeAll(Collection<?> c);
- boolean retainAll(Collection<?> c);
- void clear();
- // Comparison and hashing
- boolean equals(Object o);
- int hashCode();
- // Positional Access Operations
- // Returns the element at the specified position in this list.
- E get(int index); // 获取指定索引处的元素
- E set(int index, E element); // 修改指定位置的元素
- void add(int index, E element);// 向指定的位置添加元素
- E remove(int index);
- // Search Operations
- int indexOf(Object o);
- int lastIndexOf(Object o);
- // List Iterators
- ListIterator<E> listIterator();
- ListIterator<E> listIterator(int index);
- // View
- List<E> subList(int fromIndex, int toIndex);
- }
如上接口定义的一些方法只针对List集合,接口中增加定义了一类有index(索引)参数的方法。由于List集合是有序的,所以可以使用index来查找集合中的元素,不管这个集合的数据类型是链表还是数组。而对于其他无序集合如Set来说,就并不需要继承这个接口。
2、ListIterator接口
对于List集合遍历操作来说,又定义出了更加细化的一个迭代接口,这个接口继承了Iterator接口,如下:
- public interface ListIterator<E> extends Iterator<E> {
- // Query Operations
- boolean hasNext(); // 是否有下一个元素
- E next(); // 获取下一个元素
- boolean hasPrevious(); // 是否有前一个元素
- E previous(); // 获取前一个元素
- int nextIndex(); // 获取下一个索引
- int previousIndex(); // 获取前一个索引
- void remove(); // 移除元素
- void set(E e); // 修改元素
- void add(E e); // 添加元素
- }
由于List集合有序,所以在遍历相关接口中定义了一些与顺序有关的操作,如获取当前元素的前一个元素、判断是否还有前一个元素等操作。
3、AbstractCollection抽象类
由于集合需要实现的基础方法很多,所以如果自己实现一个基于List接口的新集合,或者是基于Set接口的新集合,那么最好继承AbstractCollection抽象类来实现。因为这个类中已经实现了基础接口中定义的常用方法,这样就可以着重来编写自己集合中独有的方法了。
其中定义的一些方法的实现非常简单,有兴趣的可以自己去研究一下。
4、AbstractList抽象类
在AbstractList中有两个重要的内部类,由这两个内部类来完成元素的迭代遍历。其类的框架图如下所示。
备注:黄色代码接口 绿钯代表实现类
(1)Itr的实现
Itr实现了Iterator接口,并对接口中定义的方法进行了实现,具体代码如下:
- private class Itr implements Iterator<E> {
- int cursor = 0; // 下一次next()方法调用时的位置
- int lastRet = -1; // 上一次游标所在的位置,所以问题比cursor小1
- int expectedModCount = modCount;
- public boolean hasNext() {
- return cursor != size();
- }
- public E next() {
- checkForComodification();
- try {
- int i = cursor;
- E next = get(i); // 获取指定索引处的元素
- lastRet = i;
- cursor = i + 1;
- return next;
- } catch (IndexOutOfBoundsException e) {
- checkForComodification();
- throw new NoSuchElementException();
- }
- }
- public void remove() {
- if (lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
- try {
- AbstractList.this.remove(lastRet);
- if (lastRet < cursor)
- cursor--;
- lastRet = -1;
- expectedModCount = modCount;
- } catch (IndexOutOfBoundsException e) {
- throw new ConcurrentModificationException();
- }
- }
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
- }//end class
类中的expectedModCount表示期待的modCount值,用来判断在遍历过程中集合是否被修改过。AbstractList包含一个modCount变量,它的初始值是0,当集合中的内容每被修改一次时(调用add(), remove()等方法),modCount加1。因此,modCount如果不变,表示集合内容未被修改。 Itr初始化时用expectedModCount记录集合的modCount变量,此后在必要的地方它会检测modCount的值:
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
类继承并实现了Iterator接口中定义的三个方法。如果一个AbstractList抽象类的具体实现类集合只是想要遍历其中的元素,则可以通过特定的方法获取到这个私有类的实例,然后调用相应方法遍历即可。获取的方法如下:
- public Iterator<E> iterator() {
- return new Itr();
- }
这样用户就可以通过调用如上的方法获得Iterator的真正类型,然后开始遍历。在讲到具体的实现类,如ArrayList时会详细进行介绍。
(2)ListItr的实现
获取到Iterator实例后,只能进行简单的顺序循环。如果还要进行更复杂的遍历操作,如获取当前位置的前一个元素、添加一个元素到当前的位置等,则需要实现ListIterator接口。ListItr类源代码如下:
- private class ListItr extends Itr implements ListIterator<E> {
- ListItr(int index) {
- cursor = index;
- }
- public boolean hasPrevious() {
- return cursor != 0;
- }
- public E previous() {
- checkForComodification();
- try {
- int i = cursor - 1;
- E previous = get(i);
- lastRet = cursor = i;
- return previous;
- } catch (IndexOutOfBoundsException e) {
- checkForComodification();
- throw new NoSuchElementException();
- }
- }
- public int nextIndex() {
- return cursor;
- }
- public int previousIndex() {
- return cursor-1;
- }
- public void set(E e) {
- if (lastRet < 0)
- throw new IllegalStateException();
- checkForComodification();
- try {
- AbstractList.this.set(lastRet, e);
- expectedModCount = modCount;
- } catch (IndexOutOfBoundsException ex) {
- throw new ConcurrentModificationException();
- }
- }
- public void add(E e) {
- checkForComodification();
- try {
- int i = cursor;
- AbstractList.this.add(i, e);
- lastRet = -1;
- cursor = i + 1;
- expectedModCount = modCount;
- } catch (IndexOutOfBoundsException ex) {
- throw new ConcurrentModificationException();
- }
- }
- }//end class
类中实现了一些新的方法,如操作游标的nextIndex()和previousIndex()方法,也支持当前元素向前或向后查找。每次在执行这些方法执行前,都要调用checkForComodificaton(),这个方法在Itr类中实现,主要功能就是检查expectedModCount变量和modCount变量是否相等,不相等就抛出ConcurrentModificationException异常。
获取ListItr实例的方法如下:
- public ListIterator<E> listIterator() {
- return listIterator(0);
- }
- public ListIterator<E> listIterator(final int index) {
- rangeCheckForAdd(index); // 检查index是否合法
- return new ListItr(index);
- }
举一个例子:
- public class test03 {
- public static void main(String args[]){
- ArrayList<String> aList=new ArrayList<String>();
- test03.test(aList);
- aList.add("dd");
- System.out.println(aList.size());// 4
- }
- public static void test(ArrayList<String> aList){
- aList.add("a");
- aList.add("b");
- aList.add("d");
- //aList.remove(2);// 抛出异常ConcurrentModificationException
- ListIterator it=aList.listIterator();
- while(it.hasNext()){
- System.out.println(it.next());
- }
- }
- }
程序运行正常,因为生成的it对象只在test()方法作用范围内有效,所以在main()方法中完全可以调用ArrayList()中的方法为集合添加元素。
(3)SubList的实现
方法的源代码如下:
- public List<E> subList(int fromIndex, int toIndex) {
- return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) :
- new SubList<>(this, fromIndex, toIndex));
- }
方法的功能就是要获取部分List集合,这个方法还涉及到了几个类,类的框架图如下。
备注: 蓝色代码抽象类
SubList和RandomAccessSubList类实现的主要功能就是实现对数组中部分连续数据进行操作。SubList类的源代码如下:
- class SubList<E> extends AbstractList<E> {
- private final AbstractList<E> l;
- private final int offset;
- private int size;
- SubList(AbstractList<E> 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;
- this.modCount = l.modCount;
- }
- public E set(int index, E element) {
- rangeCheck(index);
- checkForComodification();
- return l.set(index+offset, element);
- }
- public E get(int index) {
- rangeCheck(index);
- checkForComodification();
- return l.get(index+offset);
- }
- public int size() {
- checkForComodification();
- return size;
- }
- public void add(int index, E element) {
- rangeCheckForAdd(index);
- checkForComodification();
- l.add(index+offset, element);
- this.modCount = l.modCount;
- size++;
- }
- public E remove(int index) {
- rangeCheck(index);
- checkForComodification();
- E result = l.remove(index+offset);
- this.modCount = l.modCount;
- size--;
- return result;
- }
- protected void removeRange(int fromIndex, int toIndex) {
- checkForComodification();
- l.removeRange(fromIndex+offset, toIndex+offset);
- this.modCount = l.modCount;
- size -= (toIndex-fromIndex);
- }
- public boolean addAll(Collection<? extends E> c) {
- return addAll(size, c);
- }
- public boolean addAll(int index, Collection<? extends E> c) {
- rangeCheckForAdd(index);
- int cSize = c.size();
- if (cSize==0)
- return false;
- checkForComodification();
- l.addAll(offset+index, c);
- this.modCount = l.modCount;
- size += cSize;
- return true;
- }
- public List<E> subList(int fromIndex, int toIndex) {
- return new SubList<>(this, fromIndex, toIndex);
- }
- private void rangeCheck(int index) {
- if (index < 0 || index >= size)
- throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
- }
- private void rangeCheckForAdd(int index) {//
- if (index < 0 || index > size)
- throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
- }
- private String outOfBoundsMsg(int index) {
- return "Index: "+index+", Size: "+size;
- }
- private void checkForComodification() {
- if (this.modCount != l.modCount)
- throw new ConcurrentModificationException();
- }
- }
可以看到,这个类中首先定义了的2个属性和1个实例,私有并且都被final修饰,也就是说,这个类的实例一旦生成,也就不可改变了。
- AbstractList<String> sub = new ArrayList<String>();
- sub.add("a");
- sub.add("b");
- sub.add("c");
- sub.add("d");
- List l = sub.subList(1, 3);
- //sub.add("e");// 抛出ConcurrentModificationException
- l.add("e");
- for (int i = 0; i < l.size(); i++) {
- System.out.println(l.get(i));// 打印的结果为:b c e,b和c来自sub,e是直接添加的
- }
如上使用循环输出,也可以使用提供的listIterator()方法进行,源代码如下:
- public Iterator<E> iterator() {
- return listIterator();
- }
- public ListIterator<E> listIterator(final int index) {
- checkForComodification();
- rangeCheckForAdd(index);
- return new ListIterator<E>() {
- private final ListIterator<E> i = l.listIterator(index+offset);// 被final修饰,不可改变
- public boolean hasNext() {
- return nextIndex() < size;
- }
- public E next() {
- if (hasNext())
- return i.next();
- else
- throw new NoSuchElementException();
- }
- public boolean hasPrevious() {
- return previousIndex() >= 0;
- }
- public E 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();
- SubList.this.modCount = l.modCount;
- size--;
- }
- public void set(E e) {
- i.set(e);
- }
- public void add(E e) {
- i.add(e);
- SubList.this.modCount = l.modCount;
- size++;
- }
- };
- }