ArrayList源码解读

来源:互联网 发布:robotmaster软件下载 编辑:程序博客网 时间:2024/06/05 02:04

一、 ArrayList概述:
ArrayList是基于数组实现的,是一个动态数组,所谓动态,就是它的容量会自动增加,ArrayList的初始容量是10。ArrayList不是线程安全的,ArrayList实现了Serializable接口,支持序列化。
二、 ArrayList的实现:
1、私有属性

private static final int DEFAULT_CAPACITY = 10;//默认初始容量private static final Object[] EMPTY_ELEMENTDATA = {};//用于空实例的共享空数组实例private transient Object[] elementData;//elementData存储ArrayList内的元素private int size;//size表示ArrayList包含的元素的数量

2、构造方法

//使用初始容量构造一个空的ArrayList,容量为10;public ArrayList() {        super();        this.elementData = EMPTY_ELEMENTDATA;    }//构造一个initialCapacity大小的ArrayList,当initialCapacity<0时,抛出IllegalArgumentException异常。public ArrayList(int initialCapacity) {        super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        this.elementData = new Object[initialCapacity];    }//构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的public ArrayList(Collection<? extends E> c) {        elementData = c.toArray();        size = elementData.length;        // c.toArray might (incorrectly) not return Object[] (see 6260652)        if (elementData.getClass() != Object[].class)            elementData = Arrays.copyOf(elementData, size, Object[].class);    }

3、一些方法

// 用指定的元素替代此列表中指定位置上的元素,并返回以前位于该位置上的元素public E set(int index, E element) {        rangeCheck(index);        E oldValue = elementData(index);        elementData[index] = element;        return oldValue;    }// 将指定的元素添加到此列表的尾部public boolean add(E e) {        ensureCapacityInternal(size + 1);  // Increments modCount!!        elementData[size++] = e;        return true;    }//将指定的元素插入此列表中的指定位置,如果当前位置有元素,则向右移动当前位于该位置的元素以及所有后续元素(将其索引加1)public void add(int index, E element) {        rangeCheckForAdd(index);        ensureCapacityInternal(size + 1);  // Increments modCount!!        System.arraycopy(elementData, index, elementData, index + 1,size - index);        elementData[index] = element;        size++;    }//按照指定collection的迭代器所返回的元素顺序,将该collection中的所有元素添加到此列表的尾部  public boolean addAll(Collection<? extends E> c) {        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);  // Increments modCount        System.arraycopy(a, 0, elementData, size, numNew);        size += numNew;        return numNew != 0;    }//从指定的位置开始,将指定collection中的所有元素插入到此列表中public boolean addAll(int index, Collection<? extends E> c) {        rangeCheckForAdd(index);        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);  // Increments modCount        int numMoved = size - index;        if (numMoved > 0)            System.arraycopy(elementData, index, elementData, index + numNew,numMoved);        System.arraycopy(a, 0, elementData, index, numNew);        size += numNew;        return numNew != 0;    } // 返回此列表中指定位置上的元素  public E get(int index) {          RangeCheck(index);          return (E) elementData[index];      }// 移除此列表中指定位置上的元素public E remove(int index) {        rangeCheck(index);        modCount++;        E oldValue = elementData(index);        int numMoved = size - index - 1;        if (numMoved > 0)            System.arraycopy(elementData, index+1, elementData, index,numMoved);        elementData[--size] = null; // clear to let GC do its work        return oldValue;    }// 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。  public boolean remove(Object o) {       // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。       if (o == null) {           for (int index = 0; index < size; index++)               if (elementData[index] == null) {                   // 类似remove(int index),移除列表中指定位置上的元素。                   fastRemove(index);                   return true;               }       } else {           for (int index = 0; index < size; index++)               if (o.equals(elementData[index])) {                   fastRemove(index);                   return true;               }           }           return false;       }  }//扩容时,会将原数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。//这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。//当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。//或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。public void ensureCapacity(int minCapacity) {        int minExpand = (elementData != EMPTY_ELEMENTDATA)            // any size if real element table            ? 0            // larger than default for empty table. It's already supposed to be            // at default size.            : DEFAULT_CAPACITY;        if (minCapacity > minExpand) {            ensureExplicitCapacity(minCapacity);        }    }//删除Arraylist中所有元素,删除之后,剩下一个空的ArrayListpublic void clear() {        modCount++;        // clear to let GC do its work        for (int i = 0; i < size; i++)            elementData[i] = null;        size = 0;    }

三、总结
1、关于ArrayList和Vector区别如下:
ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。
Vector提供indexOf(obj, start)接口,ArrayList没有。
Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。
2、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为10,带有Collection参数的构造方法,将Collection转化为数组赋

给ArrayList的实现数组elementData。
3、ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。Arrays.copyof()实际上是在其内部又创建了一个长度为

newlength的数组,调用System.arraycopy()方法,将原来数组中的元素复制到了新的数组中。System.arraycopy()方法被标记了native,调用

了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证

同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时

用该方法,以取得更高的效率。
4、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,

插入删除元素的效率低。
5、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。

1 0
原创粉丝点击