关闭

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

92人阅读 评论(0) 收藏 举报
分类:

本章分析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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:47607次
    • 积分:885
    • 等级:
    • 排名:千里之外
    • 原创:37篇
    • 转载:30篇
    • 译文:0篇
    • 评论:3条
    博客专栏
    最新评论