zoukankan      html  css  js  c++  java
  • JDK源码-ArrayList源码

    1,继承结构图:
         -1,ArrayList继承AbstractList抽象类,实现List、RandomAccess、Cloneable、Serializable接口。
         -2,查看List接口的继承关系,我们看到List接口实现了Collection接口。Collection接口是基本集合类接口。查看Collection接口的说明:
    /**
    * The root interface in the <i>collection hierarchy</i>. A collection
    * represents a group of objects, known as its <i>elements</i>. Some
    * collections allow duplicate elements and others do not. Some are ordered
    * and others unordered.
         -3,查看AbstractList分支继承关系,AbstractList继承AbstractCollection,实现List接口。
         -4,查看AbstractCollection,可以看到该类实现Collection接口。
         -5,Collection接口最终实现迭代器接口:Iterable。
    2,从用自上而下的方式来一步一步查看源码。
    3,Iterable接口:
    package java.lang;
     
    import java.util.Iterator;
     
    /** Implementing this interface allows an object to be the target of
    * the "foreach" statement.
    * @since 1.5
    */
    public interface Iterable<T> {
     
    /**
    * Returns an iterator over a set of elements of type T.
    *
    * @return an Iterator.
    */
    Iterator<T> iterator();
    }
    Iterable接口类源码很简单,我们知道该接口属于迭代器模式,用来实现迭代遍历集合类。所以Collection接口实现了该接口,标识Collecttion的所有子类都可以使用迭代器方式遍历。
    Iterable接口比较重要的子类我们可以看Iterator接口,如下,我摘录出了该接口的方法。
    public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
    }
    4,Collection接口,我们通过JavaDoc文档可以查看对应的子类
    * <p>This interface is a member of the
    * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    * Java Collections Framework</a>.
    *
    * @author Josh Bloch
    * @author Neal Gafter
    * @version 1.55, 04/21/06
    * @see Set
    * @see List
    * @see Map
    * @see SortedSet
    * @see SortedMap
    * @see HashSet
    * @see TreeSet
    * @see ArrayList
    * @see LinkedList
    * @see Vector
    * @see Collections
    * @see Arrays
    * @see AbstractCollection
    * @since 1.2
    */
    可以看到对应的都实现此接口,接口中定义了集合类常用到的方法。
    5,AbstractCollection
    public abstract class AbstractCollection<E> implements Collection<E>
    该类主要实现了部分共用的方法,比如:
    /**
    * {@inheritDoc}
    *
    * <p>This implementation returns <tt>size() == 0</tt>.
    */
    public boolean isEmpty() {
    return size() == 0;
    }
    public boolean contains(Object o) {
    Iterator<E> e = iterator();
    if (o==null) {
    while (e.hasNext())
    if (e.next()==null)
    return true;
    } else {
    while (e.hasNext())
    if (o.equals(e.next()))
    return true;
    }
    return false;
    }
    public boolean remove(Object o) {
    Iterator<E> e = iterator();
    if (o==null) {
    while (e.hasNext()) {
    if (e.next()==null) {
    e.remove();
    return true;
    }
    }
    } else {
    while (e.hasNext()) {
    if (o.equals(e.next())) {
    e.remove();
    return true;
    }
    }
    }
    return false;
    }
    public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    Iterator<? extends E> e = c.iterator();
    while (e.hasNext()) {
    if (add(e.next()))
    modified = true;
    }
    return modified;
    }
    主要实现了以上的方法,我们发现以上方法有个共同特点,就是具体操作是通过其他方法来实现的,比如addAll方法,主要是通过add方法来实现的。
    6,List接口,List接口继承了Collection接口,对Collection接口进行了一些扩展。
        -1,因为List存储的是顺序集合类。
    An ordered collection (also known as a <i>sequence</i>).
        -2,允许重复元素。
    Unlike sets, lists typically allow duplicate elements.
        -3,提供ListIterator来实现元素迭代。ListIterator继承自Iterator接口,并提供一些扩展方法。
    The <tt>List</tt> interface provides a special iterator, called a
    * <tt>ListIterator</tt>, that allows element insertion and replacement, and
    * bidirectional access in addition to the normal operations that the
    * <tt>Iterator</tt> interface provides.
        -4,提供一些其他扩展操作方法。
    7,ArrayList源码。
        -1,ArrayList是List的可变数组实现方式。实现了所有List接口的方法,大致同Vector类,只不过此类是不同步的。
               size  isEmpty  get  set  iterator  listIterator操作都以固定时间运行。即,添加n个元素需要O(n)事件运行,其他的操作也以线性时间运行。
                每个ArrayList都存在一个capacity的实例,该实例用来存储List对应数组的长度。
                在添加大数据操作时候,可以使用ensureCapacity操作来提前扩展大小。此操作是非线程安全的,如果多个线程同时访问一个ArrayList实例,而至少有一个线程从结构上(增加或者删除元素,或修改底层数组大小,不包含元素值的修改)修改了列表,那么它必须保持外部同步。一般通过封装该列表的对象进行同步操作来完成,如果不存该对象,可以使用Collections.synchronizedList方法包装列表实现。
    List list = Collections.synchronizedList(new ArrayList(...));
                使用迭代器遍历元素的时候,在创建迭代器之后,除非通过迭代器自身的remove或add方法从结构上对列表进行修改,否则在任何时间以任何方式修改都会抛出异常。
        以上均为API对ArrayList的描述。我们可以使用代码对以上内容进行测试:
        a. 测试  size  isEmpty  get  set  iterator  listIterator  add方法时间。
        
    public class TestAdd {
     
    public static void main(String[] args) {
    long startTime = System.currentTimeMillis();
    List<Integer> lists = new ArrayList<Integer>();
    //测试add方法
    for(int i = 0 ; i < 1000000; i++){
    lists.add(1);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("add添加1000000元素,用时: " + (endTime - startTime));//输出32
    //add 一个元素的时间
    startTime = System.currentTimeMillis();
    lists.add(2);
    endTime = System.currentTimeMillis();
    System.out.println("add添加1元素,用时: " + (endTime - startTime));//输出0
    //get 一个元素
    startTime = System.currentTimeMillis();
    lists.get(2);
    endTime = System.currentTimeMillis();
    System.out.println("get元素,用时: " + (endTime - startTime));//输出0
    }
    }
       b.  使用capacity元素完成初始化操作:
    long startTime = System.currentTimeMillis();
    List<Integer> lists = new ArrayList<Integer>(1000000);
    //测试add方法
    for(int i = 0 ; i < 1000000; i++){
    lists.add(1);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("add添加1000000元素,用时: " + (endTime - startTime));//输出12
       c.使用迭代器遍历ArrayList
        
    startTime = System.currentTimeMillis();
    Iterator<Integer> iter = lists.iterator();
    int a ;
    while(iter.hasNext()){
    a = iter.next();
    }
    endTime = System.currentTimeMillis();
    System.out.println("迭代器元素,用时: " + (endTime - startTime));//输出33
    -2,成员变量:
        elementData: 数组,用来存储ArrayList对应的元素列表。使用capacity来存储数组长度。
    private transient Object[] elementData;
        size:ArrayList存储元素的长度。
        modCount:此变量属于父类AbstractList。该元素记录了从结构上修改次列表的次数。此字段由iterator和listIterator方法返回的迭代器和列表迭代器实现。
        -3,构造函数:
        public ArrayList(int initCapacity):如果初始化参数小于0则抛出异常,否则初始化列表中的数组。
    public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
    throw new IllegalArgumentException("Illegal Capacity: "+
    initialCapacity);
    this.elementData = new Object[initialCapacity];
    }
        public  ArrayList():初始化一个长度为10的数组。
    public ArrayList() {
    this(10);
    }
        public ArrayList(Collection<? extends e> c):构建一个包含c中所有元素的列表,元素顺序按照Iterator返回的顺序排列。
    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)//如注释c.toArray可能返回非数组对象,所以此处需要判断,确保返回的为数组对象
    elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    使用到了Arrays.copyOf方法,我们可以进一步查看该方法:
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    T[] copy = ((Object)newType == (Object)Object[].class)
    ? (T[]) new Object[newLength]
    : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
    Math.min(original.length, newLength));
    return copy;
    }
    查看System.arraycopy源码:
    public static native void arraycopy(Object src, int srcPos,
    Object dest, int destPos,
    int length);
        -4,方法:
        add(E e):添加对应元素到数组中。add方法记调用了ensureCapacity方法,保证数组元素不越界,然后对数组元素的末尾增加了当前元素。
    public boolean add(E e) {
    ensureCapacity(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
    }
        ensureCapacity(int minCapacity):该方法判断数组元素是否已经超过了当前ArrayList中的数组长度,如果超过则增加长度。
    public void ensureCapacity(int minCapacity) {
    modCount++;
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
    Object oldData[] = elementData;
    int newCapacity = (oldCapacity * 3)/2 + 1;
    if (newCapacity < minCapacity)
    newCapacity = minCapacity;
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    }
        add(int index, E element):在数组固定位置添加元素。
         remove(int index):移除制定索引的元素。
    public E remove(int index) {
    RangeCheck(index);//确保索引位置未超出最大size,超出则抛出异常。
     
    modCount++;//记录表结构修改计数器
    E oldValue = (E) elementData[index];
     
    int numMoved = size - index - 1;
    if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
    numMoved);//将后续元素均向前移动一位
    elementData[--size] = null; // Let gc do its work
     
    return oldValue;
    }
        get(int index):获取制定索引元素
    public E get(int index) {
    RangeCheck(index);
     
    return (E) elementData[index];
    }
        set(int index, E e):更换制定索引元素值,使用e替换,并返回原有值。

    ArrayList的操作基本都很简单,包括源代码,相对来说还是比较简单。看此处的代码的时候,建议先学习数据结构的线性表后,再来看次部分的代码。
    欢迎转载,但转载请注明原文链接[博客园: http://www.cnblogs.com/jingLongJun/]
    [CSDN博客:http://blog.csdn.net/mergades]。
    如相关博文涉及到版权问题,请联系本人。
  • 相关阅读:
    I NEED A OFFER!
    水题 Codeforces Round #303 (Div. 2) A. Toy Cars
    模拟 HDOJ 5099 Comparison of Android versions
    模拟 HDOJ 5095 Linearization of the kernel functions in SVM
    贪心 HDOJ 5090 Game with Pearls
    Kruskal HDOJ 1863 畅通工程
    Kruskal HDOJ 1233 还是畅通工程
    并查集 HDOJ 1232 畅通工程
    DFS/并查集 Codeforces Round #286 (Div. 2) B
    水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta's Gift
  • 原文地址:https://www.cnblogs.com/jingLongJun/p/4491055.html
Copyright © 2011-2022 走看看