JDK源码走读(3):容器之ArrayList

来源:互联网 发布:在线seo外链工具软件 编辑:程序博客网 时间:2024/06/06 09:28

本章分析List系列中的ArrayList,有些与PriorityQueue类似,比如底层同样采取数组存储元素,也涉及到扩容操作等;也有不同之处,比如PriorityQueue不允许存入的元素为null,而ArrayList允许将null元素存放其中。

一、 类实现/继承体系结构

为了对整个List实现/继承体系有个全貌,先将体系结构图画出来:

二、 关键数据成员

(1)存储结构

transient Object[]elementData; // non-private to simplify nested class access;

以数组作为底层存储结构,存放ArrayList链表中的元素

数组elementData的默认初始化大小(DEFAULT_CAPACITY)是10。

(2)数组存放的元素个数

private int size;

三、 构造函数

ArrayList提供了多种形式的构造函数,在此不一一列举,就参数来说,主要包括,数组链表(elementData)初始化大小(initialCapacity)值、其他集合

这里要讲下以下几个构造函数:

publicArrayList (Collection<? extends E> c):利用另一个集合初始化ArrayList,要求就是负责初始化集合中的元素类型是E或者是E的子类。

四、 一些链表操作

(1)  void trimToSize():将ArrayList的存储空间压缩到size大小,将空闲空间还给系统

做法就是Arrays.copyOf(elementData, size)新生成一个数组,赋值给elementData;

(2)  void sort(Comparator<? super E> c):对链表进行排序,调用了Arrays.sort接口

Arrays.sort((E[])elementData, 0, size, c);

这里有一点,因为ArrayList接口都不是线程安全的,在一个线程操作链表时,并不能防止其他线程也在操作链表,有可能在排序时,其他线程已经修改了链表,修改有可能导致排序结果不准确,所以,这时就需要抛出异常:

public void sort(Comparator<?super E> c) {    final int expectedModCount = modCount;    Arrays.sort((E[]) elementData, 0, size, c);    if (modCount != expectedModCount) {            throw newConcurrentModificationException();        }        modCount++;    }

五、 增

(1)  boolean addAll(Collection<? extends E> c):将容器c中元素添加到ArrayList的末尾

首先检查容量capacity,然后执行拷贝

        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size +numNew);  // Increments modCount        System.arraycopy(a, 0, elementData,size, numNew);        size += numNew; 

System.arraycopy参数含义:

第一个参数:数据来源数组;

第二个参数:数据来源数组的起始拷贝索引index;

第三个参数:数据目标数组;

第四个参数:数据目标数组起始拷贝索引index;

第五个参数:拷贝元素的个数;

(2)  boolean addAll(int index, Collection<?extends E> c):将容器c中元素添加到ArrayList中,添加的起始位置是在index处

如果index不是数组末尾,就涉及到两次拷贝:

if (size - index > 0)    System.arraycopy(elementData,index, elementData, index+numNew, numMoved);                              System.arraycopy(a,0, elementData, index, numNew);

六、 删

(1)  E remove(int index):删除位于index位置的元素

不可避免的,会将数组elementData 在index之后元素前移一个位置,复杂度O(n)

System.arraycopy(elementData,index+1, elementData, index, numMoved);

(2)  boolean removeAll(Collection<?> c):删除ArrayList中的集合c中的元素,即求交集

这里使用了一个叫做batchRemove的私有函数:

    private booleanbatchRemove(Collection<?> c, boolean complement) {        final Object[] elementData =this.elementData;        int r = 0, w = 0;        boolean modified = false;        try {            for (; r < size; r++)                if (c.contains(elementData[r])== complement)                    elementData[w++] =elementData[r];        } finally {            // Preserve behavioralcompatibility with AbstractCollection,            // even if c.contains() throws.            if (r != size) {                System.arraycopy(elementData,r,                                 elementData,w,                                 size - r);                w += size - r;            }            if (w != size) {                // clear to let GC do its work                for (int i = w; i < size;i++)                    elementData[i] = null;                modCount += size - w;                size = w;                modified = true;            }        }        return modified;    }

七、 改

八、 查

peek():返回队列queue中index=0的元素,queue[0];如果为空,则返回null。

contains(Object o):public booleancontains(Object o) {        return indexOf(o) != -1;}

九、 遍历

ArrayList实现了内部类Itr:

private class Itrimplements Iterator<E>

ArrayList还实现了内部类ListItr,其继承自Itr,并实现了接口ListIterator:

private class ListItrextends Itr implements ListIterator<E>

而接口ListIterator继承自Iterator接口:interface ListIterator<E>extends Iterator<E>

所以,可以通过两种迭代器遍历ArrayList,分别对应到Itr和ListItr:

Iterator<String>iter = names.iterator();ListIterator<String>iter = names.listIterator()/names.listIterator(1);

 Itr就是通用的迭代器,提供hasNext和next接口:

public Iterator<E> iterator() {        return new Itr();}

ListIterator针对ArrayList,除了提供hasNext和next接口,还提供遍历的起始点index,并且还可以逆序遍历:

   public ListIterator<E> listIterator()/listIterator(index) {        return new ListItr(0)/ListItr(index);   }   ListIterator<String> iter = names.listIterator(3);   while (iter.hasPrevious()) {      System.out.println(iter.previous());   }

十、 子链表subList

ArrayList实现了List<E>subList(int fromIndex, int toIndex)

List<E>subList(int fromIndex, int toIndex)接口即返回一个新生成的子链表subList对象。

0 0
原创粉丝点击